From 58be81ed301d96045bca2b85f3b838910efcfde4 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 7 Nov 2008 18:19:19 +0000 Subject: uwb: fix races between events and neh timers Always use del_timer_sync() before freeing nehs. Destroy all nehs after stopping the radio controller and before cleaning up the reservation manager. Handle the timer running after an event has removed the neh. This fixes various oopses that may occur if a radio controller is removed while a neh timer is still active. Signed-off-by: David Vrabel --- drivers/uwb/neh.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'drivers/uwb/neh.c') diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 9b4eb64327a..48b4ece1a62 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c @@ -254,7 +254,6 @@ error_kzalloc: static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) { - del_timer(&neh->timer); __uwb_rc_ctx_put(rc, neh); list_del(&neh->list_node); } @@ -275,6 +274,7 @@ void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); + del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } @@ -438,9 +438,10 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size rceb->bEventContext, size); } else { neh = uwb_rc_neh_lookup(rc, rceb); - if (neh) + if (neh) { + del_timer_sync(&neh->timer); uwb_rc_neh_cb(neh, rceb, size); - else + } else dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext, size); @@ -562,16 +563,22 @@ EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); */ void uwb_rc_neh_error(struct uwb_rc *rc, int error) { - struct uwb_rc_neh *neh, *next; + struct uwb_rc_neh *neh; unsigned long flags; - BUG_ON(error >= 0); - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { + for (;;) { + spin_lock_irqsave(&rc->neh_lock, flags); + if (list_empty(&rc->neh_list)) { + spin_unlock_irqrestore(&rc->neh_lock, flags); + break; + } + neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); + spin_unlock_irqrestore(&rc->neh_lock, flags); + + del_timer_sync(&neh->timer); uwb_rc_neh_cb(neh, NULL, error); } - spin_unlock_irqrestore(&rc->neh_lock, flags); } EXPORT_SYMBOL_GPL(uwb_rc_neh_error); @@ -583,10 +590,14 @@ static void uwb_rc_neh_timer(unsigned long arg) unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); - __uwb_rc_neh_rm(rc, neh); + if (neh->context) + __uwb_rc_neh_rm(rc, neh); + else + neh = NULL; spin_unlock_irqrestore(&rc->neh_lock, flags); - uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); + if (neh) + uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); } /** Initializes the @rc's neh subsystem @@ -605,12 +616,19 @@ void uwb_rc_neh_create(struct uwb_rc *rc) void uwb_rc_neh_destroy(struct uwb_rc *rc) { unsigned long flags; - struct uwb_rc_neh *neh, *next; + struct uwb_rc_neh *neh; - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { + for (;;) { + spin_lock_irqsave(&rc->neh_lock, flags); + if (list_empty(&rc->neh_list)) { + spin_unlock_irqrestore(&rc->neh_lock, flags); + break; + } + neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); + spin_unlock_irqrestore(&rc->neh_lock, flags); + + del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } - spin_unlock_irqrestore(&rc->neh_lock, flags); } -- cgit v1.2.3 From 02f11ee181baa562df23e105ba930902f0d0b1bf Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 12 Dec 2008 13:28:48 +0000 Subject: uwb: fix memory leak in uwb_rc_notif() Don't leak memory in uwb_rc_notif() if certain non-standard events are received. Signed-off-by: David Vrabel --- drivers/uwb/neh.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/uwb/neh.c') diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 48b4ece1a62..6df18eda1fd 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c @@ -349,7 +349,7 @@ struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc, } -/** +/* * Process notifications coming from the radio control interface * * @rc: UWB Radio Control Interface descriptor @@ -401,23 +401,6 @@ void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size) uwb_evt->notif.size = size; uwb_evt->notif.rceb = rceb; - switch (le16_to_cpu(rceb->wEvent)) { - /* Trap some vendor specific events - * - * FIXME: move this to handling in ptc-est, where we - * register a NULL event handler for these two guys - * using the Intel IDs. - */ - case 0x0103: - dev_info(dev, "FIXME: DEVICE ADD\n"); - return; - case 0x0104: - dev_info(dev, "FIXME: DEVICE RM\n"); - return; - default: - break; - } - uwbd_event_queue(uwb_evt); } -- cgit v1.2.3 From bce83697c5fe84a7a5d38c96fbbe43b4bc028c3e Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 22 Dec 2008 18:22:50 +0000 Subject: uwb: use dev_dbg() for debug messages Instead of the home-grown d_fnstart(), d_fnend() and d_printf() macros, use dev_dbg() or remove the message entirely. Signed-off-by: David Vrabel --- drivers/uwb/neh.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/uwb/neh.c') diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 6df18eda1fd..0af8916d9be 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c @@ -86,8 +86,6 @@ #include #include "uwb-internal.h" -#define D_LOCAL 0 -#include /* * UWB Radio Controller Notification/Event Handle @@ -479,8 +477,6 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) size_t size, real_size, event_size; int needtofree; - d_fnstart(3, dev, "(rc %p buf %p %zu buf_size)\n", rc, buf, buf_size); - d_printf(2, dev, "groking event block: %zu bytes\n", buf_size); itr = buf; size = buf_size; while (size > 0) { @@ -528,10 +524,7 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) itr += real_size; size -= real_size; - d_printf(2, dev, "consumed %zd bytes, %zu left\n", - event_size, size); } - d_fnend(3, dev, "(rc %p buf %p %zu buf_size) = void\n", rc, buf, buf_size); } EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); -- cgit v1.2.3