summary refs log tree commit diff
path: root/drivers/uwb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2012-04-16 15:28:28 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-18 13:15:51 -0700
commit9426cd05682745d1024dbabdec5631309bd2f480 (patch)
treea2db2587a008c8286cfc11fa6111bafd59faa4e9 /drivers/uwb
parent2fbe2bf1fd37f9d99950bd8d8093623cf22cf08b (diff)
downloadlinux-9426cd05682745d1024dbabdec5631309bd2f480.tar.gz
uwb: fix use of del_timer_sync() in interrupt
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>
Diffstat (limited to 'drivers/uwb')
-rw-r--r--drivers/uwb/neh.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c
index a269937be1b8..8cb71bb333c2 100644
--- a/drivers/uwb/neh.c
+++ b/drivers/uwb/neh.c
@@ -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