==================================================================
[ INFO: inconsistent lock state ]
2.6.37-Linus-03737-g0c21e3a-dirty #251
---------------------------------
inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
takes:
(&(&list->lock)->rlock#5){?.-...}, at: skb_queue_tail+0x26/0x60
{HARDIRQ-ON-W} state was registered at:
__lock_acquire+0xb25/0x1cc0
lock_acquire+0x93/0x130
_raw_spin_lock+0x2c/0x40
ieee80211_rx_handlers+0x27/0x1c80 [mac80211]
ieee80211_prepare_and_rx_handle+0x238/0x900 [mac80211]
ieee80211_rx+0x31a/0x940 [mac80211]
ieee80211_tasklet_handler+0xc1/0xd0 [mac80211]
tasklet_action+0x73/0x120
__do_softirq+0xce/0x200
==================================================================
The reason is that ieee80211_rx_handlers() locks rx->local->rx_skb_queue.lock
using spin_lock(), but skb_queue_tail() locks the same entity with
spin_lock_irqsave().
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
Johannes,
I think this is correct. At least the lockdep warning goes away on my
machine.
Larry
---
===================================================================
@@ -2465,6 +2465,7 @@ static void ieee80211_rx_handlers(struct
{
ieee80211_rx_result res = RX_DROP_MONITOR;
struct sk_buff *skb;
+ unsigned long flags;
#define CALL_RXH(rxh) \
do { \
@@ -2473,14 +2474,14 @@ static void ieee80211_rx_handlers(struct
goto rxh_next; \
} while (0);
- spin_lock(&rx->local->rx_skb_queue.lock);
+ spin_lock_irqsave(&rx->local->rx_skb_queue.lock, flags);
if (rx->local->running_rx_handler)
goto unlock;
rx->local->running_rx_handler = true;
while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) {
- spin_unlock(&rx->local->rx_skb_queue.lock);
+ spin_unlock_irqrestore(&rx->local->rx_skb_queue.lock, flags);
/*
* all the other fields are valid across frames
@@ -2513,14 +2514,14 @@ static void ieee80211_rx_handlers(struct
rxh_next:
ieee80211_rx_handlers_result(rx, res);
- spin_lock(&rx->local->rx_skb_queue.lock);
+ spin_lock_irqsave(&rx->local->rx_skb_queue.lock, flags);
#undef CALL_RXH
}
rx->local->running_rx_handler = false;
unlock:
- spin_unlock(&rx->local->rx_skb_queue.lock);
+ spin_unlock_irqrestore(&rx->local->rx_skb_queue.lock, flags);
}
static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)