wcn36xx: handle connection loss indication
authorBenjamin Li <benl@squareup.com>
Wed, 1 Sep 2021 18:06:05 +0000 (11:06 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:16:00 +0000 (19:16 +0100)
commit d6dbce453b19c64b96f3e927b10230f9a704b504 upstream.

Firmware sends delete_sta_context_ind when it detects the AP has gone
away in STA mode. Right now the handler for that indication only handles
AP mode; fix it to also handle STA mode.

Cc: stable@vger.kernel.org
Signed-off-by: Benjamin Li <benl@squareup.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Loic Poulain <loic.poulain@linaro.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210901180606.11686-1-benl@squareup.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/ath/wcn36xx/smd.c

index 57fa857b290b79a86fc8ffe0e46d52c052bc34c2..f6bea896abe85120192efcaf8f8d309ea713bf0b 100644 (file)
@@ -2623,30 +2623,52 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
                                              size_t len)
 {
        struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
-       struct wcn36xx_vif *tmp;
+       struct wcn36xx_vif *vif_priv;
+       struct ieee80211_vif *vif;
+       struct ieee80211_bss_conf *bss_conf;
        struct ieee80211_sta *sta;
+       bool found = false;
 
        if (len != sizeof(*rsp)) {
                wcn36xx_warn("Corrupted delete sta indication\n");
                return -EIO;
        }
 
-       wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
-                   rsp->addr2, rsp->sta_id);
+       wcn36xx_dbg(WCN36XX_DBG_HAL,
+                   "delete station indication %pM index %d reason %d\n",
+                   rsp->addr2, rsp->sta_id, rsp->reason_code);
 
-       list_for_each_entry(tmp, &wcn->vif_list, list) {
+       list_for_each_entry(vif_priv, &wcn->vif_list, list) {
                rcu_read_lock();
-               sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
-               if (sta)
-                       ieee80211_report_low_ack(sta, 0);
+               vif = wcn36xx_priv_to_vif(vif_priv);
+
+               if (vif->type == NL80211_IFTYPE_STATION) {
+                       /* We could call ieee80211_find_sta too, but checking
+                        * bss_conf is clearer.
+                        */
+                       bss_conf = &vif->bss_conf;
+                       if (vif_priv->sta_assoc &&
+                           !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
+                               found = true;
+                               wcn36xx_dbg(WCN36XX_DBG_HAL,
+                                           "connection loss bss_index %d\n",
+                                           vif_priv->bss_index);
+                               ieee80211_connection_loss(vif);
+                       }
+               } else {
+                       sta = ieee80211_find_sta(vif, rsp->addr2);
+                       if (sta) {
+                               found = true;
+                               ieee80211_report_low_ack(sta, 0);
+                       }
+               }
+
                rcu_read_unlock();
-               if (sta)
+               if (found)
                        return 0;
        }
 
-       wcn36xx_warn("STA with addr %pM and index %d not found\n",
-                    rsp->addr2,
-                    rsp->sta_id);
+       wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
        return -ENOENT;
 }