uwb: fix use of del_timer_sync() in interrupt
authorOliver Neukum <oliver@neukum.org>
Mon, 16 Apr 2012 13:28:28 +0000 (15:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Apr 2012 20:15:51 +0000 (13:15 -0700)
del_timer_sync() cannot be used in interrupt.
Replace it with del_timer() and a flag

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/uwb/neh.c

index a269937be1b8230898f991eb5f430e3f79ac9824..8cb71bb333c2ea830881ddc8bf19afd4096b3d60 100644 (file)
@@ -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