|
@@ -107,6 +107,7 @@ struct uwb_rc_neh {
|
|
|
u8 evt_type;
|
|
|
__le16 evt;
|
|
|
u8 context;
|
|
|
+ u8 completed;
|
|
|
uwb_rc_cmd_cb_f cb;
|
|
|
void *arg;
|
|
|
|
|
@@ -409,6 +410,7 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
|
|
|
struct device *dev = &rc->uwb_dev.dev;
|
|
|
struct uwb_rc_neh *neh;
|
|
|
struct uwb_rceb *notif;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
if (rceb->bEventContext == 0) {
|
|
|
notif = kmalloc(size, GFP_ATOMIC);
|
|
@@ -422,7 +424,11 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
|
|
|
} else {
|
|
|
neh = uwb_rc_neh_lookup(rc, rceb);
|
|
|
if (neh) {
|
|
|
- del_timer_sync(&neh->timer);
|
|
|
+ spin_lock_irqsave(&rc->neh_lock, flags);
|
|
|
+ /* to guard against a timeout */
|
|
|
+ neh->completed = 1;
|
|
|
+ del_timer(&neh->timer);
|
|
|
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
|
|
|
uwb_rc_neh_cb(neh, rceb, size);
|
|
|
} else
|
|
|
dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n",
|
|
@@ -568,6 +574,10 @@ static void uwb_rc_neh_timer(unsigned long arg)
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&rc->neh_lock, flags);
|
|
|
+ if (neh->completed) {
|
|
|
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (neh->context)
|
|
|
__uwb_rc_neh_rm(rc, neh);
|
|
|
else
|