mirror of
https://github.com/torvalds/linux.git
synced 2024-12-20 18:11:47 +00:00
wl12xx: reset link Tx queues when freeing it
Before, the link was first freed (invalidating it in the map), and later on vif removal, all valid wlvif-related links were reset. Since these links were already invalid, we failed to reset them. The bug was made worse by op_stop, which set the tx_queue_count to 0 arbitrarily. This resulted in a negative tx_queue_count in some scenarios. Fix this by resetting the Tx-queues of a link when freeing it. Add a WARN_ON and reset all link Tx-queues in op_stop, to avoid a negative tx_queue_count. [changed WARN_ON to WARN_ON_ONCE -- Luca] Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
0b0e32b792
commit
6246ca003f
@ -485,6 +485,13 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
|
||||
__clear_bit(*hlid, wl->links_map);
|
||||
__clear_bit(*hlid, wlvif->links_map);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
/*
|
||||
* At this point op_tx() will not add more packets to the queues. We
|
||||
* can purge them.
|
||||
*/
|
||||
wl1271_tx_reset_link_queues(wl, *hlid);
|
||||
|
||||
*hlid = WL12XX_INVALID_LINK_ID;
|
||||
}
|
||||
|
||||
|
@ -4228,7 +4228,6 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
|
||||
clear_bit(hlid, wlvif->ap.sta_hlid_map);
|
||||
memset(wl->links[hlid].addr, 0, ETH_ALEN);
|
||||
wl->links[hlid].ba_bitmap = 0;
|
||||
wl1271_tx_reset_link_queues(wl, hlid);
|
||||
__clear_bit(hlid, &wl->ap_ps_map);
|
||||
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
wl12xx_free_link(wl, wlvif, &hlid);
|
||||
|
@ -527,6 +527,7 @@ static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl,
|
||||
if (skb) {
|
||||
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
|
||||
wl->tx_queue_count[q]--;
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
@ -602,6 +603,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
|
||||
skb = wl->dummy_packet;
|
||||
q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
|
||||
wl->tx_queue_count[q]--;
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
@ -959,7 +961,6 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
else
|
||||
wlvif->sta.ba_rx_bitmap = 0;
|
||||
|
||||
wl1271_tx_reset_link_queues(wl, i);
|
||||
wl->links[i].allocated_pkts = 0;
|
||||
wl->links[i].prev_freed_pkts = 0;
|
||||
}
|
||||
@ -973,8 +974,14 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
wl->tx_queue_count[i] = 0;
|
||||
/* only reset the queues if something bad happened */
|
||||
if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) {
|
||||
for (i = 0; i < WL12XX_MAX_LINKS; i++)
|
||||
wl1271_tx_reset_link_queues(wl, i);
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
wl->tx_queue_count[i] = 0;
|
||||
}
|
||||
|
||||
wl->stopped_queues_map = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user