mac80211: mark patches accepted upstream
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch
diff --git a/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch b/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch
new file mode 100644 (file)
index 0000000..9d58345
--- /dev/null
@@ -0,0 +1,655 @@
+From: Alexander Wetzel <alexander@wetzel-home.de>
+Date: Sun, 9 Oct 2022 18:30:40 +0200
+Subject: [PATCH] wifi: mac80211: Drop support for TX push path
+
+All drivers are now using mac80211 internal queues (iTXQs).
+Drop mac80211 internal support for the old push path.
+
+Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4339,9 +4339,6 @@ static int ieee80211_get_txq_stats(struc
+       struct ieee80211_sub_if_data *sdata;
+       int ret = 0;
+-      if (!local->ops->wake_tx_queue)
+-              return 1;
+-
+       spin_lock_bh(&local->fq.lock);
+       rcu_read_lock();
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -663,9 +663,7 @@ void debugfs_hw_add(struct ieee80211_loc
+       DEBUGFS_ADD_MODE(force_tx_status, 0600);
+       DEBUGFS_ADD_MODE(aql_enable, 0600);
+       DEBUGFS_ADD(aql_pending);
+-
+-      if (local->ops->wake_tx_queue)
+-              DEBUGFS_ADD_MODE(aqm, 0600);
++      DEBUGFS_ADD_MODE(aqm, 0600);
+       DEBUGFS_ADD_MODE(airtime_flags, 0600);
+--- a/net/mac80211/debugfs_netdev.c
++++ b/net/mac80211/debugfs_netdev.c
+@@ -677,8 +677,7 @@ static void add_common_files(struct ieee
+       DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
+       DEBUGFS_ADD(hw_queues);
+-      if (sdata->local->ops->wake_tx_queue &&
+-          sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
++      if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+           sdata->vif.type != NL80211_IFTYPE_NAN)
+               DEBUGFS_ADD(aqm);
+ }
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -1056,10 +1056,8 @@ void ieee80211_sta_debugfs_add(struct st
+       DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
+       DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
+-      if (local->ops->wake_tx_queue) {
+-              DEBUGFS_ADD(aqm);
+-              DEBUGFS_ADD(airtime);
+-      }
++      DEBUGFS_ADD(aqm);
++      DEBUGFS_ADD(airtime);
+       if (wiphy_ext_feature_isset(local->hw.wiphy,
+                                   NL80211_EXT_FEATURE_AQL))
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2290,7 +2290,6 @@ void ieee80211_wake_queue_by_reason(stru
+ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
+                                   enum queue_stop_reason reason,
+                                   bool refcounted);
+-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
+ void ieee80211_add_pending_skb(struct ieee80211_local *local,
+                              struct sk_buff *skb);
+ void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -458,12 +458,6 @@ static void ieee80211_do_stop(struct iee
+       if (cancel_scan)
+               ieee80211_scan_cancel(local);
+-      /*
+-       * Stop TX on this interface first.
+-       */
+-      if (!local->ops->wake_tx_queue && sdata->dev)
+-              netif_tx_stop_all_queues(sdata->dev);
+-
+       ieee80211_roc_purge(local, sdata);
+       switch (sdata->vif.type) {
+@@ -811,13 +805,6 @@ static void ieee80211_uninit(struct net_
+       ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
+ }
+-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+-                                       struct sk_buff *skb,
+-                                       struct net_device *sb_dev)
+-{
+-      return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
+-}
+-
+ static void
+ ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ {
+@@ -831,7 +818,6 @@ static const struct net_device_ops ieee8
+       .ndo_start_xmit         = ieee80211_subif_start_xmit,
+       .ndo_set_rx_mode        = ieee80211_set_multicast_list,
+       .ndo_set_mac_address    = ieee80211_change_mac,
+-      .ndo_select_queue       = ieee80211_netdev_select_queue,
+       .ndo_get_stats64        = ieee80211_get_stats64,
+ };
+@@ -939,7 +925,6 @@ static const struct net_device_ops ieee8
+       .ndo_start_xmit         = ieee80211_subif_start_xmit_8023,
+       .ndo_set_rx_mode        = ieee80211_set_multicast_list,
+       .ndo_set_mac_address    = ieee80211_change_mac,
+-      .ndo_select_queue       = ieee80211_netdev_select_queue,
+       .ndo_get_stats64        = ieee80211_get_stats64,
+       .ndo_fill_forward_path  = ieee80211_netdev_fill_forward_path,
+ };
+@@ -1441,35 +1426,6 @@ int ieee80211_do_open(struct wireless_de
+       ieee80211_recalc_ps(local);
+-      if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+-          sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+-          local->ops->wake_tx_queue) {
+-              /* XXX: for AP_VLAN, actually track AP queues */
+-              if (dev)
+-                      netif_tx_start_all_queues(dev);
+-      } else if (dev) {
+-              unsigned long flags;
+-              int n_acs = IEEE80211_NUM_ACS;
+-              int ac;
+-
+-              if (local->hw.queues < IEEE80211_NUM_ACS)
+-                      n_acs = 1;
+-
+-              spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+-              if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
+-                  (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
+-                   skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
+-                      for (ac = 0; ac < n_acs; ac++) {
+-                              int ac_queue = sdata->vif.hw_queue[ac];
+-
+-                              if (local->queue_stop_reasons[ac_queue] == 0 &&
+-                                  skb_queue_empty(&local->pending[ac_queue]))
+-                                      netif_start_subqueue(dev, ac);
+-                      }
+-              }
+-              spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+-      }
+-
+       set_bit(SDATA_STATE_RUNNING, &sdata->state);
+       return 0;
+@@ -1499,17 +1455,12 @@ static void ieee80211_if_setup(struct ne
+ {
+       ether_setup(dev);
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
++      dev->priv_flags |= IFF_NO_QUEUE;
+       dev->netdev_ops = &ieee80211_dataif_ops;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ieee80211_if_free;
+ }
+-static void ieee80211_if_setup_no_queue(struct net_device *dev)
+-{
+-      ieee80211_if_setup(dev);
+-      dev->priv_flags |= IFF_NO_QUEUE;
+-}
+-
+ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
+                                       struct ieee80211_sub_if_data *sdata,
+                                       struct sk_buff *skb)
+@@ -2094,9 +2045,7 @@ int ieee80211_if_add(struct ieee80211_lo
+       struct net_device *ndev = NULL;
+       struct ieee80211_sub_if_data *sdata = NULL;
+       struct txq_info *txqi;
+-      void (*if_setup)(struct net_device *dev);
+       int ret, i;
+-      int txqs = 1;
+       ASSERT_RTNL();
+@@ -2119,30 +2068,18 @@ int ieee80211_if_add(struct ieee80211_lo
+                                sizeof(void *));
+               int txq_size = 0;
+-              if (local->ops->wake_tx_queue &&
+-                  type != NL80211_IFTYPE_AP_VLAN &&
++              if (type != NL80211_IFTYPE_AP_VLAN &&
+                   (type != NL80211_IFTYPE_MONITOR ||
+                    (params->flags & MONITOR_FLAG_ACTIVE)))
+                       txq_size += sizeof(struct txq_info) +
+                                   local->hw.txq_data_size;
+-              if (local->ops->wake_tx_queue) {
+-                      if_setup = ieee80211_if_setup_no_queue;
+-              } else {
+-                      if_setup = ieee80211_if_setup;
+-                      if (local->hw.queues >= IEEE80211_NUM_ACS)
+-                              txqs = IEEE80211_NUM_ACS;
+-              }
+-
+               ndev = alloc_netdev_mqs(size + txq_size,
+                                       name, name_assign_type,
+-                                      if_setup, txqs, 1);
++                                      ieee80211_if_setup, 1, 1);
+               if (!ndev)
+                       return -ENOMEM;
+-              if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len)
+-                      ndev->tx_queue_len = local->hw.wiphy->tx_queue_len;
+-
+               dev_net_set(ndev, wiphy_net(local->hw.wiphy));
+               ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -630,7 +630,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+       if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
+                   !ops->add_interface || !ops->remove_interface ||
+-                  !ops->configure_filter))
++                  !ops->configure_filter || !ops->wake_tx_queue))
+               return NULL;
+       if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
+@@ -719,9 +719,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+       if (!ops->set_key)
+               wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+-      if (ops->wake_tx_queue)
+-              wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
+-
++      wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
+       wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
+@@ -834,10 +832,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+               atomic_set(&local->agg_queue_stop[i], 0);
+       }
+       tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending);
+-
+-      if (ops->wake_tx_queue)
+-              tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
+-
++      tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
+       tasklet_setup(&local->tasklet, ieee80211_tasklet_handler);
+       skb_queue_head_init(&local->skb_queue);
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1571,9 +1571,6 @@ static void sta_ps_start(struct sta_info
+       ieee80211_clear_fast_xmit(sta);
+-      if (!sta->sta.txq[0])
+-              return;
+-
+       for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
+               struct ieee80211_txq *txq = sta->sta.txq[tid];
+               struct txq_info *txqi = to_txq_info(txq);
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -140,17 +140,15 @@ static void __cleanup_single_sta(struct
+               atomic_dec(&ps->num_sta_ps);
+       }
+-      if (sta->sta.txq[0]) {
+-              for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+-                      struct txq_info *txqi;
++      for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
++              struct txq_info *txqi;
+-                      if (!sta->sta.txq[i])
+-                              continue;
++              if (!sta->sta.txq[i])
++                      continue;
+-                      txqi = to_txq_info(sta->sta.txq[i]);
++              txqi = to_txq_info(sta->sta.txq[i]);
+-                      ieee80211_txq_purge(local, txqi);
+-              }
++              ieee80211_txq_purge(local, txqi);
+       }
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+@@ -425,8 +423,7 @@ void sta_info_free(struct ieee80211_loca
+       sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
+-      if (sta->sta.txq[0])
+-              kfree(to_txq_info(sta->sta.txq[0]));
++      kfree(to_txq_info(sta->sta.txq[0]));
+       kfree(rcu_dereference_raw(sta->sta.rates));
+ #ifdef CPTCFG_MAC80211_MESH
+       kfree(sta->mesh);
+@@ -527,6 +524,8 @@ __sta_info_alloc(struct ieee80211_sub_if
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_hw *hw = &local->hw;
+       struct sta_info *sta;
++      void *txq_data;
++      int size;
+       int i;
+       sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
+@@ -597,21 +596,18 @@ __sta_info_alloc(struct ieee80211_sub_if
+       sta->last_connected = ktime_get_seconds();
+-      if (local->ops->wake_tx_queue) {
+-              void *txq_data;
+-              int size = sizeof(struct txq_info) +
+-                         ALIGN(hw->txq_data_size, sizeof(void *));
++      size = sizeof(struct txq_info) +
++             ALIGN(hw->txq_data_size, sizeof(void *));
+-              txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
+-              if (!txq_data)
+-                      goto free;
++      txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
++      if (!txq_data)
++              goto free;
+-              for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+-                      struct txq_info *txq = txq_data + i * size;
++      for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
++              struct txq_info *txq = txq_data + i * size;
+-                      /* might not do anything for the bufferable MMPDU TXQ */
+-                      ieee80211_txq_init(sdata, sta, txq, i);
+-              }
++              /* might not do anything for the (bufferable) MMPDU TXQ */
++              ieee80211_txq_init(sdata, sta, txq, i);
+       }
+       if (sta_prepare_rate_control(local, sta, gfp))
+@@ -685,8 +681,7 @@ __sta_info_alloc(struct ieee80211_sub_if
+       return sta;
+ free_txq:
+-      if (sta->sta.txq[0])
+-              kfree(to_txq_info(sta->sta.txq[0]));
++      kfree(to_txq_info(sta->sta.txq[0]));
+ free:
+       sta_info_free_link(&sta->deflink);
+ #ifdef CPTCFG_MAC80211_MESH
+@@ -1959,9 +1954,6 @@ ieee80211_sta_ps_deliver_response(struct
+                * TIM recalculation.
+                */
+-              if (!sta->sta.txq[0])
+-                      return;
+-
+               for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
+                       if (!sta->sta.txq[tid] ||
+                           !(driver_release_tids & BIT(tid)) ||
+@@ -2446,7 +2438,7 @@ static void sta_set_tidstats(struct sta_
+               tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
+       }
+-      if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) {
++      if (tid < IEEE80211_NUM_TIDS) {
+               spin_lock_bh(&local->fq.lock);
+               rcu_read_lock();
+@@ -2774,9 +2766,6 @@ unsigned long ieee80211_sta_last_active(
+ static void sta_update_codel_params(struct sta_info *sta, u32 thr)
+ {
+-      if (!sta->sdata->local->ops->wake_tx_queue)
+-              return;
+-
+       if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
+               sta->cparams.target = MS2TIME(50);
+               sta->cparams.interval = MS2TIME(300);
+--- a/net/mac80211/tdls.c
++++ b/net/mac80211/tdls.c
+@@ -1016,7 +1016,6 @@ ieee80211_tdls_prep_mgmt_packet(struct w
+               skb->priority = 256 + 5;
+               break;
+       }
+-      skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
+       /*
+        * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1599,9 +1599,6 @@ int ieee80211_txq_setup_flows(struct iee
+       bool supp_vht = false;
+       enum nl80211_band band;
+-      if (!local->ops->wake_tx_queue)
+-              return 0;
+-
+       ret = fq_init(fq, 4096);
+       if (ret)
+               return ret;
+@@ -1649,9 +1646,6 @@ void ieee80211_txq_teardown_flows(struct
+ {
+       struct fq *fq = &local->fq;
+-      if (!local->ops->wake_tx_queue)
+-              return;
+-
+       kfree(local->cvars);
+       local->cvars = NULL;
+@@ -1668,8 +1662,7 @@ static bool ieee80211_queue_skb(struct i
+       struct ieee80211_vif *vif;
+       struct txq_info *txqi;
+-      if (!local->ops->wake_tx_queue ||
+-          sdata->vif.type == NL80211_IFTYPE_MONITOR)
++      if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+               return false;
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+@@ -4185,12 +4178,7 @@ void __ieee80211_subif_start_xmit(struct
+       if (IS_ERR(sta))
+               sta = NULL;
+-      if (local->ops->wake_tx_queue) {
+-              u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+-              skb_set_queue_mapping(skb, queue);
+-              skb_get_hash(skb);
+-      }
+-
++      skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+       ieee80211_aggr_check(sdata, sta, skb);
+       sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
+@@ -4501,11 +4489,7 @@ static void ieee80211_8023_xmit(struct i
+       struct tid_ampdu_tx *tid_tx;
+       u8 tid;
+-      if (local->ops->wake_tx_queue) {
+-              u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+-              skb_set_queue_mapping(skb, queue);
+-              skb_get_hash(skb);
+-      }
++      skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+       if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
+           test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+@@ -4759,9 +4743,6 @@ void ieee80211_tx_pending(struct tasklet
+                       if (!txok)
+                               break;
+               }
+-
+-              if (skb_queue_empty(&local->pending[i]))
+-                      ieee80211_propagate_queue_wake(local, i);
+       }
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+@@ -5954,10 +5935,9 @@ int ieee80211_tx_control_port(struct wip
+       }
+       if (!IS_ERR(sta)) {
+-              u16 queue = __ieee80211_select_queue(sdata, sta, skb);
++              u16 queue = ieee80211_select_queue(sdata, sta, skb);
+               skb_set_queue_mapping(skb, queue);
+-              skb_get_hash(skb);
+               /*
+                * for MLO STA, the SA should be the AP MLD address, but
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -446,39 +446,6 @@ void ieee80211_wake_txqs(struct tasklet_
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ }
+-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
+-{
+-      struct ieee80211_sub_if_data *sdata;
+-      int n_acs = IEEE80211_NUM_ACS;
+-
+-      if (local->ops->wake_tx_queue)
+-              return;
+-
+-      if (local->hw.queues < IEEE80211_NUM_ACS)
+-              n_acs = 1;
+-
+-      list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-              int ac;
+-
+-              if (!sdata->dev)
+-                      continue;
+-
+-              if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
+-                  local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
+-                      continue;
+-
+-              for (ac = 0; ac < n_acs; ac++) {
+-                      int ac_queue = sdata->vif.hw_queue[ac];
+-
+-                      if (ac_queue == queue ||
+-                          (sdata->vif.cab_queue == queue &&
+-                           local->queue_stop_reasons[ac_queue] == 0 &&
+-                           skb_queue_empty(&local->pending[ac_queue])))
+-                              netif_wake_subqueue(sdata->dev, ac);
+-              }
+-      }
+-}
+-
+ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
+                                  enum queue_stop_reason reason,
+                                  bool refcounted,
+@@ -509,11 +476,7 @@ static void __ieee80211_wake_queue(struc
+               /* someone still has this queue stopped */
+               return;
+-      if (skb_queue_empty(&local->pending[queue])) {
+-              rcu_read_lock();
+-              ieee80211_propagate_queue_wake(local, queue);
+-              rcu_read_unlock();
+-      } else
++      if (!skb_queue_empty(&local->pending[queue]))
+               tasklet_schedule(&local->tx_pending_tasklet);
+       /*
+@@ -523,12 +486,10 @@ static void __ieee80211_wake_queue(struc
+        * release someone's lock, but it is fine because all the callers of
+        * __ieee80211_wake_queue call it right before releasing the lock.
+        */
+-      if (local->ops->wake_tx_queue) {
+-              if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
+-                      tasklet_schedule(&local->wake_txqs_tasklet);
+-              else
+-                      _ieee80211_wake_txqs(local, flags);
+-      }
++      if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
++              tasklet_schedule(&local->wake_txqs_tasklet);
++      else
++              _ieee80211_wake_txqs(local, flags);
+ }
+ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
+@@ -585,10 +546,6 @@ 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) {
+-                              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);
+--- a/net/mac80211/wme.c
++++ b/net/mac80211/wme.c
+@@ -122,6 +122,9 @@ u16 ieee80211_select_queue_80211(struct
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       u8 *p;
++      /* Ensure hash is set prior to potential SW encryption */
++      skb_get_hash(skb);
++
+       if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) ||
+           local->hw.queues < IEEE80211_NUM_ACS)
+               return 0;
+@@ -141,12 +144,15 @@ u16 ieee80211_select_queue_80211(struct
+       return ieee80211_downgrade_queue(sdata, NULL, skb);
+ }
+-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+-                           struct sta_info *sta, struct sk_buff *skb)
++u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
++                         struct sta_info *sta, struct sk_buff *skb)
+ {
+       struct mac80211_qos_map *qos_map;
+       bool qos;
++      /* Ensure hash is set prior to potential SW encryption */
++      skb_get_hash(skb);
++
+       /* all mesh/ocb stations are required to support WME */
+       if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+                   sdata->vif.type == NL80211_IFTYPE_OCB))
+@@ -176,59 +182,6 @@ u16 __ieee80211_select_queue(struct ieee
+       return ieee80211_downgrade_queue(sdata, sta, skb);
+ }
+-
+-/* Indicate which queue to use. */
+-u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+-                         struct sk_buff *skb)
+-{
+-      struct ieee80211_local *local = sdata->local;
+-      struct sta_info *sta = NULL;
+-      const u8 *ra = NULL;
+-      u16 ret;
+-
+-      /* when using iTXQ, we can do this later */
+-      if (local->ops->wake_tx_queue)
+-              return 0;
+-
+-      if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
+-              skb->priority = 0; /* required for correct WPA/11i MIC */
+-              return 0;
+-      }
+-
+-      rcu_read_lock();
+-      switch (sdata->vif.type) {
+-      case NL80211_IFTYPE_AP_VLAN:
+-              sta = rcu_dereference(sdata->u.vlan.sta);
+-              if (sta)
+-                      break;
+-              fallthrough;
+-      case NL80211_IFTYPE_AP:
+-              ra = skb->data;
+-              break;
+-      case NL80211_IFTYPE_STATION:
+-              /* might be a TDLS station */
+-              sta = sta_info_get(sdata, skb->data);
+-              if (sta)
+-                      break;
+-
+-              ra = sdata->deflink.u.mgd.bssid;
+-              break;
+-      case NL80211_IFTYPE_ADHOC:
+-              ra = skb->data;
+-              break;
+-      default:
+-              break;
+-      }
+-
+-      if (!sta && ra && !is_multicast_ether_addr(ra))
+-              sta = sta_info_get(sdata, ra);
+-
+-      ret = __ieee80211_select_queue(sdata, sta, skb);
+-
+-      rcu_read_unlock();
+-      return ret;
+-}
+-
+ /**
+  * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
+  *
+--- a/net/mac80211/wme.h
++++ b/net/mac80211/wme.h
+@@ -13,10 +13,8 @@
+ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
+                                struct sk_buff *skb,
+                                struct ieee80211_hdr *hdr);
+-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+-                           struct sta_info *sta, struct sk_buff *skb);
+ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+-                         struct sk_buff *skb);
++                         struct sta_info *sta, struct sk_buff *skb);
+ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
+                          struct sk_buff *skb);