| From 6b07d9ca9b5363dda959b9582a3fc9c0b89ef3b5 Mon Sep 17 00:00:00 2001 |
| From: Felix Fietkau <nbd@nbd.name> |
| Date: Tue, 2 Aug 2016 11:13:41 +0200 |
| Subject: mac80211: fix purging multicast PS buffer queue |
| |
| From: Felix Fietkau <nbd@nbd.name> |
| |
| commit 6b07d9ca9b5363dda959b9582a3fc9c0b89ef3b5 upstream. |
| |
| The code currently assumes that buffered multicast PS frames don't have |
| a pending ACK frame for tx status reporting. |
| However, hostapd sends a broadcast deauth frame on teardown for which tx |
| status is requested. This can lead to the "Have pending ack frames" |
| warning on module reload. |
| Fix this by using ieee80211_free_txskb/ieee80211_purge_tx_queue. |
| |
| Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/mac80211/cfg.c | 2 +- |
| net/mac80211/tx.c | 6 +++--- |
| 2 files changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/net/mac80211/cfg.c |
| +++ b/net/mac80211/cfg.c |
| @@ -869,7 +869,7 @@ static int ieee80211_stop_ap(struct wiph |
| |
| /* free all potentially still buffered bcast frames */ |
| local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); |
| - skb_queue_purge(&sdata->u.ap.ps.bc_buf); |
| + ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf); |
| |
| mutex_lock(&local->mtx); |
| ieee80211_vif_copy_chanctx_to_vlans(sdata, true); |
| --- a/net/mac80211/tx.c |
| +++ b/net/mac80211/tx.c |
| @@ -365,7 +365,7 @@ static void purge_old_ps_buffers(struct |
| skb = skb_dequeue(&ps->bc_buf); |
| if (skb) { |
| purged++; |
| - dev_kfree_skb(skb); |
| + ieee80211_free_txskb(&local->hw, skb); |
| } |
| total += skb_queue_len(&ps->bc_buf); |
| } |
| @@ -448,7 +448,7 @@ ieee80211_tx_h_multicast_ps_buf(struct i |
| if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) { |
| ps_dbg(tx->sdata, |
| "BC TX buffer full - dropping the oldest frame\n"); |
| - dev_kfree_skb(skb_dequeue(&ps->bc_buf)); |
| + ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf)); |
| } else |
| tx->local->total_ps_buffered++; |
| |
| @@ -4055,7 +4055,7 @@ ieee80211_get_buffered_bc(struct ieee802 |
| sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); |
| if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb)) |
| break; |
| - dev_kfree_skb_any(skb); |
| + ieee80211_free_txskb(hw, skb); |
| } |
| |
| info = IEEE80211_SKB_CB(skb); |