Access to tx_q_limit needs to be serialized among the possibly multiple writers to the tx queue. A mutex will do fine for that. Signed-off-by: David Mosberger-Tang <davidm@xxxxxxxxxx> --- drivers/net/wireless/microchip/wilc1000/cfg80211.c | 2 ++ drivers/net/wireless/microchip/wilc1000/netdev.h | 2 ++ drivers/net/wireless/microchip/wilc1000/wlan.c | 5 ++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index d352b7dd03283..0fcc064254f1e 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -1672,6 +1672,7 @@ static void wlan_init_locks(struct wilc *wl) spin_lock_init(&wl->txq_spinlock); mutex_init(&wl->txq_add_to_head_cs); + mutex_init(&wl->tx_q_limit_lock); init_waitqueue_head(&wl->txq_event); init_completion(&wl->cfg_event); @@ -1688,6 +1689,7 @@ void wlan_deinit_locks(struct wilc *wilc) mutex_destroy(&wilc->txq_add_to_head_cs); mutex_destroy(&wilc->vif_mutex); mutex_destroy(&wilc->deinit_lock); + mutex_destroy(&wilc->tx_q_limit_lock); cleanup_srcu_struct(&wilc->srcu); } diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h index 650b40961cf98..e247f92a409e0 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.h +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h @@ -257,6 +257,8 @@ struct wilc { atomic_t txq_entries; struct txq_fw_recv_queue_stat fw[NQUEUES]; + /* protect tx_q_limit state */ + struct mutex tx_q_limit_lock; struct wilc_tx_queue_status tx_q_limit; struct rxq_entry_t rxq_head; diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index f82857cebe35e..9b6605e9df296 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -279,13 +279,12 @@ static void init_q_limits(struct wilc *wl) static bool is_ac_q_limit(struct wilc *wl, u8 q_num) { - unsigned long flags; struct wilc_tx_queue_status *q = &wl->tx_q_limit; u8 end_index; u8 q_limit; bool ret = false; - spin_lock_irqsave(&wl->txq_spinlock, flags); + mutex_lock(&wl->tx_q_limit_lock); end_index = q->end_index; q->cnt[q->buffer[end_index]] -= factors[q->buffer[end_index]]; @@ -306,7 +305,7 @@ static bool is_ac_q_limit(struct wilc *wl, u8 q_num) if (skb_queue_len(&wl->txq[q_num]) <= q_limit) ret = true; - spin_unlock_irqrestore(&wl->txq_spinlock, flags); + mutex_unlock(&wl->tx_q_limit_lock); return ret; } -- 2.25.1