|
@@ -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);
|
|
|
}
|