@@ -1579,16 +1561,39 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
tmp = skb_queue_len(&pending);
filtered += tmp - count;
count = tmp;
-
- spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
- skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
- spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
- tmp = skb_queue_len(&pending);
- buffered += tmp - count;
}
+ skb_queue_head_init(&pending);
ieee80211_add_pending_skbs(local, &pending);
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+ if (!sta->sta.txq[i])
+ continue;
+
+ txqi = to_txq_info(sta->sta.txq[i]);
+ clear_bit(IEEE80211_TXQ_STOP_PS, &txqi->flags);
+ }
+
+ /* Make sure TX path has stopped setting txq_buffered_tids */
+ synchronize_net();
+
We are atomic here and can't sleep. Working on that now, but this gets
surprisingly complex fast.
Review of the rest is still welcome but this patch must not be merged as
it is.
It kind of looks like the current (unpatched) code is not only sending
out filtered frames after iTXQ but also misses the required
rcu_read_lock to be allowed to call schedule_and_wake_txq() in this
function when called from drv_deliver_wk()...
Alexander