ath10k: fix per-vif queue locking
authorMichal Kazior <michal.kazior@tieto.com>
Thu, 9 Jul 2015 11:08:38 +0000 (13:08 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Sat, 11 Jul 2015 16:06:26 +0000 (19:06 +0300)
Whenever any vdev was supposed to be paused all Tx
queues were stopped (except offchannel) instead of
only these associated with the given vdev.

This caused subtle issues with
multi-channel/multi-vif scenarios, e.g.
authentication of station vif could sometimes fail
depending on fw tx pause request timing.

Fixes: b4aa539dd8f2 ("ath10k: implement tx pause wmi event")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.h
drivers/net/wireless/ath/ath10k/wmi-tlv.c

index 8049d77cfc3503a727a63944d00f6c57e18b508d..b2e3fe9a9caeb56999022acb60ba5d43af75d32f 100644 (file)
@@ -3034,38 +3034,16 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif,
 
        lockdep_assert_held(&ar->htt.tx_lock);
 
-       switch (pause_id) {
-       case WMI_TLV_TX_PAUSE_ID_MCC:
-       case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
-       case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PS:
-       case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
-               switch (action) {
-               case WMI_TLV_TX_PAUSE_ACTION_STOP:
-                       ath10k_mac_vif_tx_lock(arvif, pause_id);
-                       break;
-               case WMI_TLV_TX_PAUSE_ACTION_WAKE:
-                       ath10k_mac_vif_tx_unlock(arvif, pause_id);
-                       break;
-               default:
-                       ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
-                                   action, arvif->vdev_id);
-                       break;
-               }
+       switch (action) {
+       case WMI_TLV_TX_PAUSE_ACTION_STOP:
+               ath10k_mac_vif_tx_lock(arvif, pause_id);
+               break;
+       case WMI_TLV_TX_PAUSE_ACTION_WAKE:
+               ath10k_mac_vif_tx_unlock(arvif, pause_id);
                break;
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
-       case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
-       case WMI_TLV_TX_PAUSE_ID_HOST:
        default:
-               /* FIXME: Some pause_ids aren't vdev specific. Instead they
-                * target peer_id and tid. Implementing these could improve
-                * traffic scheduling fairness across multiple connected
-                * stations in AP/IBSS modes.
-                */
-               ath10k_dbg(ar, ATH10K_DBG_MAC,
-                          "mac ignoring unsupported tx pause vdev %i id %d\n",
-                          arvif->vdev_id, pause_id);
+               ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
+                           action, arvif->vdev_id);
                break;
        }
 }
@@ -3082,12 +3060,15 @@ static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac,
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
        struct ath10k_mac_tx_pause *arg = data;
 
+       if (arvif->vdev_id != arg->vdev_id)
+               return;
+
        ath10k_mac_vif_handle_tx_pause(arvif, arg->pause_id, arg->action);
 }
 
-void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id,
-                               enum wmi_tlv_tx_pause_id pause_id,
-                               enum wmi_tlv_tx_pause_action action)
+void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
+                                    enum wmi_tlv_tx_pause_id pause_id,
+                                    enum wmi_tlv_tx_pause_action action)
 {
        struct ath10k_mac_tx_pause arg = {
                .vdev_id = vdev_id,
index b291f063705c3bb816f811aad450e9549aca5dfb..e3cefe4c7cfd04aa4e8c142282330068209bcb68 100644 (file)
@@ -61,9 +61,9 @@ int ath10k_mac_vif_chan(struct ieee80211_vif *vif,
 
 void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
-void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id,
-                               enum wmi_tlv_tx_pause_id pause_id,
-                               enum wmi_tlv_tx_pause_action action);
+void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
+                                    enum wmi_tlv_tx_pause_id pause_id,
+                                    enum wmi_tlv_tx_pause_action action);
 
 u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
                             u8 hw_rate);
index ced35a1e06750c0ff4641ee3b1ae1900ef69ed18..4189d4a90ce0a8e6eeca9a9f2a25a1818fce3548 100644 (file)
@@ -377,12 +377,34 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
                   "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
                   pause_id, action, vdev_map, peer_id, tid_map);
 
-       for (vdev_id = 0; vdev_map; vdev_id++) {
-               if (!(vdev_map & BIT(vdev_id)))
-                       continue;
-
-               vdev_map &= ~BIT(vdev_id);
-               ath10k_mac_handle_tx_pause(ar, vdev_id, pause_id, action);
+       switch (pause_id) {
+       case WMI_TLV_TX_PAUSE_ID_MCC:
+       case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
+       case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
+       case WMI_TLV_TX_PAUSE_ID_AP_PS:
+       case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
+               for (vdev_id = 0; vdev_map; vdev_id++) {
+                       if (!(vdev_map & BIT(vdev_id)))
+                               continue;
+
+                       vdev_map &= ~BIT(vdev_id);
+                       ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
+                                                       action);
+               }
+               break;
+       case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
+       case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
+       case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
+       case WMI_TLV_TX_PAUSE_ID_HOST:
+               ath10k_dbg(ar, ATH10K_DBG_MAC,
+                          "mac ignoring unsupported tx pause id %d\n",
+                          pause_id);
+               break;
+       default:
+               ath10k_dbg(ar, ATH10K_DBG_MAC,
+                          "mac ignoring unknown tx pause vdev %d\n",
+                          pause_id);
+               break;
        }
 
        kfree(tb);