diff options
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/300-mac80211-add-stop-start-logic-for-software-TXQs.patch')
-rw-r--r-- | package/kernel/mac80211/patches/subsys/300-mac80211-add-stop-start-logic-for-software-TXQs.patch | 272 |
1 files changed, 0 insertions, 272 deletions
diff --git a/package/kernel/mac80211/patches/subsys/300-mac80211-add-stop-start-logic-for-software-TXQs.patch b/package/kernel/mac80211/patches/subsys/300-mac80211-add-stop-start-logic-for-software-TXQs.patch deleted file mode 100644 index 422e9c2977..0000000000 --- a/package/kernel/mac80211/patches/subsys/300-mac80211-add-stop-start-logic-for-software-TXQs.patch +++ /dev/null @@ -1,272 +0,0 @@ -From: Manikanta Pubbisetty <mpubbise@codeaurora.org> -Date: Wed, 11 Jul 2018 00:12:53 +0530 -Subject: [PATCH] mac80211: add stop/start logic for software TXQs - -Sometimes, it is required to stop the transmissions momentarily and -resume it later; stopping the txqs becomes very critical in scenarios where -the packet transmission has to be ceased completely. For example, during -the hardware restart, during off channel operations, -when initiating CSA(upon detecting a radar on the DFS channel), etc. - -The TX queue stop/start logic in mac80211 works well in stopping the TX -when drivers make use of netdev queues, i.e, when Qdiscs in network layer -take care of traffic scheduling. Since the devices implementing -wake_tx_queue can run without Qdiscs, packets will be handed to mac80211 -directly without queueing them in the netdev queues. - -Also, mac80211 does not invoke any of the -netif_stop_*/netif_wake_* APIs if wake_tx_queue is implemented. -Since the queues are not stopped in this case, transmissions can continue -and this will impact negatively on the operation of the wireless device. - -For example, -During hardware restart, we stop the netdev queues so that packets are -not sent to the driver. Since ath10k implements wake_tx_queue, -TX queues will not be stopped and packets might reach the hardware while -it is restarting; this can make hardware unresponsive and the only -possible option for recovery is to reboot the entire system. - -There is another problem to this, it is observed that the packets -were sent on the DFS channel for a prolonged duration after radar -detection impacting the channel closing time. - -We can still invoke netif stop/wake APIs when wake_tx_queue is implemented -but this could lead to packet drops in network layer; adding stop/start -logic for software TXQs in mac80211 instead makes more sense; the change -proposed adds the same in mac80211. - -Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org> -Signed-off-by: Johannes Berg <johannes.berg@intel.com> ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1504,6 +1504,8 @@ enum ieee80211_vif_flags { - * @drv_priv: data area for driver use, will always be aligned to - * sizeof(void \*). - * @txq: the multicast data TX queue (if driver uses the TXQ abstraction) -+ * @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped, -+ * protected by fq->lock. - */ - struct ieee80211_vif { - enum nl80211_iftype type; -@@ -1528,6 +1530,8 @@ struct ieee80211_vif { - - unsigned int probe_req_reg; - -+ bool txqs_stopped[IEEE80211_NUM_ACS]; -+ - /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); - }; ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -818,6 +818,7 @@ enum txq_info_flags { - IEEE80211_TXQ_STOP, - IEEE80211_TXQ_AMPDU, - IEEE80211_TXQ_NO_AMSDU, -+ IEEE80211_TXQ_STOP_NETIF_TX, - }; - - /** -@@ -1226,6 +1227,7 @@ struct ieee80211_local { - - struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; - struct tasklet_struct tx_pending_tasklet; -+ struct tasklet_struct wake_txqs_tasklet; - - atomic_t agg_queue_stop[IEEE80211_MAX_QUEUES]; - -@@ -2039,6 +2041,7 @@ void ieee80211_txq_remove_vlan(struct ie - struct ieee80211_sub_if_data *sdata); - void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats, - struct txq_info *txqi); -+void ieee80211_wake_txqs(unsigned long data); - void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, - u16 transaction, u16 auth_alg, u16 status, - const u8 *extra, size_t extra_len, const u8 *bssid, ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -686,6 +686,10 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, - (unsigned long)local); - -+ if (ops->wake_tx_queue) -+ tasklet_init(&local->wake_txqs_tasklet, ieee80211_wake_txqs, -+ (unsigned long)local); -+ - tasklet_init(&local->tasklet, - ieee80211_tasklet_handler, - (unsigned long) local); ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -3482,13 +3482,19 @@ struct sk_buff *ieee80211_tx_dequeue(str - struct ieee80211_tx_info *info; - struct ieee80211_tx_data tx; - ieee80211_tx_result r; -- struct ieee80211_vif *vif; -+ struct ieee80211_vif *vif = txq->vif; - - spin_lock_bh(&fq->lock); - -- if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) -+ if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) || -+ test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags)) - goto out; - -+ if (vif->txqs_stopped[ieee80211_ac_from_tid(txq->tid)]) { -+ set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags); -+ goto out; -+ } -+ - /* Make sure fragments stay together. */ - skb = __skb_dequeue(&txqi->frags); - if (skb) -@@ -3583,6 +3589,7 @@ begin: - } - - IEEE80211_SKB_CB(skb)->control.vif = vif; -+ - out: - spin_unlock_bh(&fq->lock); - ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -240,6 +240,99 @@ __le16 ieee80211_ctstoself_duration(stru - } - EXPORT_SYMBOL(ieee80211_ctstoself_duration); - -+static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) -+{ -+ struct ieee80211_local *local = sdata->local; -+ struct ieee80211_vif *vif = &sdata->vif; -+ struct fq *fq = &local->fq; -+ struct ps_data *ps = NULL; -+ struct txq_info *txqi; -+ struct sta_info *sta; -+ int i; -+ -+ spin_lock_bh(&fq->lock); -+ -+ if (sdata->vif.type == NL80211_IFTYPE_AP) -+ ps = &sdata->bss->ps; -+ -+ sdata->vif.txqs_stopped[ac] = false; -+ -+ list_for_each_entry_rcu(sta, &local->sta_list, list) { -+ if (sdata != sta->sdata) -+ continue; -+ -+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { -+ struct ieee80211_txq *txq = sta->sta.txq[i]; -+ -+ txqi = to_txq_info(txq); -+ -+ if (ac != txq->ac) -+ continue; -+ -+ if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX, -+ &txqi->flags)) -+ continue; -+ -+ spin_unlock_bh(&fq->lock); -+ drv_wake_tx_queue(local, txqi); -+ spin_lock_bh(&fq->lock); -+ } -+ } -+ -+ if (!vif->txq) -+ goto out; -+ -+ txqi = to_txq_info(vif->txq); -+ -+ if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags) || -+ (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac) -+ goto out; -+ -+ spin_unlock_bh(&fq->lock); -+ -+ drv_wake_tx_queue(local, txqi); -+ return; -+out: -+ spin_unlock_bh(&fq->lock); -+} -+ -+void ieee80211_wake_txqs(unsigned long data) -+{ -+ struct ieee80211_local *local = (struct ieee80211_local *)data; -+ struct ieee80211_sub_if_data *sdata; -+ int n_acs = IEEE80211_NUM_ACS; -+ unsigned long flags; -+ int i; -+ -+ rcu_read_lock(); -+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); -+ -+ if (local->hw.queues < IEEE80211_NUM_ACS) -+ n_acs = 1; -+ -+ for (i = 0; i < local->hw.queues; i++) { -+ if (local->queue_stop_reasons[i]) -+ continue; -+ -+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -+ list_for_each_entry_rcu(sdata, &local->interfaces, list) { -+ int ac; -+ -+ for (ac = 0; ac < n_acs; ac++) { -+ int ac_queue = sdata->vif.hw_queue[ac]; -+ -+ if (ac_queue == i || -+ sdata->vif.cab_queue == i) -+ __ieee80211_wake_txqs(sdata, ac); -+ } -+ } -+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); -+ } -+ -+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -+ rcu_read_unlock(); -+} -+ - void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) - { - struct ieee80211_sub_if_data *sdata; -@@ -308,6 +401,9 @@ static void __ieee80211_wake_queue(struc - rcu_read_unlock(); - } else - tasklet_schedule(&local->tx_pending_tasklet); -+ -+ if (local->ops->wake_tx_queue) -+ tasklet_schedule(&local->wake_txqs_tasklet); - } - - void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, -@@ -351,9 +447,6 @@ static void __ieee80211_stop_queue(struc - if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue])) - return; - -- if (local->ops->wake_tx_queue) -- return; -- - if (local->hw.queues < IEEE80211_NUM_ACS) - n_acs = 1; - -@@ -366,8 +459,15 @@ static void __ieee80211_stop_queue(struc - - for (ac = 0; ac < n_acs; ac++) { - if (sdata->vif.hw_queue[ac] == queue || -- sdata->vif.cab_queue == queue) -- netif_stop_subqueue(sdata->dev, ac); -+ sdata->vif.cab_queue == queue) { -+ if (!local->ops->wake_tx_queue) { -+ netif_stop_subqueue(sdata->dev, ac); -+ continue; -+ } -+ spin_lock(&local->fq.lock); -+ sdata->vif.txqs_stopped[ac] = true; -+ spin_unlock(&local->fq.lock); -+ } - } - } - rcu_read_unlock(); |