ath11k: fix mgmt_tx_wmi cmd sent to FW for deleted vdev
authorSathishkumar Muruganandam <murugana@codeaurora.org>
Tue, 28 Apr 2020 04:45:25 +0000 (10:15 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 4 May 2020 08:53:53 +0000 (11:53 +0300)
In Multi-AP VAP scenario with frequent interface up-down, there is a
chance that ath11k_mgmt_over_wmi_tx_work() will dequeue a skb
corresponding to currently deleted/stopped vdev.

FW will assert on receiving mgmt_tx_wmi cmd for already deleted vdev.
Hence adding validation checks for arvif present on the corresponding
ar before sending mgmt_tx_wmi cmd.

Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1588049126-1490-2-git-send-email-murugana@codeaurora.org
drivers/net/wireless/ath/ath11k/mac.c

index 065b7d6..2b3a63a 100644 (file)
@@ -3793,15 +3793,30 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
 
        while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
                info = IEEE80211_SKB_CB(skb);
-               arvif = ath11k_vif_to_arvif(info->control.vif);
-
-               ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
-               if (ret) {
-                       ath11k_warn(ar->ab, "failed to transmit management frame %d\n",
-                                   ret);
+               if (!info->control.vif) {
+                       ath11k_warn(ar->ab, "no vif found for mgmt frame, flags 0x%x\n",
+                                   info->control.flags);
                        ieee80211_free_txskb(ar->hw, skb);
+                       continue;
+               }
+
+               arvif = ath11k_vif_to_arvif(info->control.vif);
+               if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
+                   arvif->is_started) {
+                       ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
+                       if (ret) {
+                               ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
+                                           arvif->vdev_id, ret);
+                               ieee80211_free_txskb(ar->hw, skb);
+                       } else {
+                               atomic_inc(&ar->num_pending_mgmt_tx);
+                       }
                } else {
-                       atomic_inc(&ar->num_pending_mgmt_tx);
+                       ath11k_warn(ar->ab,
+                                   "dropping mgmt frame for vdev %d, flags 0x%x is_started %d\n",
+                                   arvif->vdev_id, info->control.flags,
+                                   arvif->is_started);
+                       ieee80211_free_txskb(ar->hw, skb);
                }
        }
 }