diff options
Diffstat (limited to 'drivers/uwb/neh.c')
-rw-r--r-- | drivers/uwb/neh.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 9b4eb64327ac..48b4ece1a627 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); } |