mt76: mt7921: fix command timeout in AP stop period
authorDeren Wu <deren.wu@mediatek.com>
Wed, 8 Jun 2022 12:53:26 +0000 (20:53 +0800)
committerFelix Fietkau <nbd@nbd.name>
Mon, 11 Jul 2022 11:40:01 +0000 (13:40 +0200)
Due to AP stop improperly, mt7921 driver would face random command timeout
by chip fw problem. Migrate AP start/stop process to .start_ap/.stop_ap and
congiure BSS network settings in both hooks.

The new flow is shown below.
* AP start
    .start_ap()
      configure BSS network resource
      set BSS to connected state
    .bss_info_changed()
      enable fw beacon offload

* AP stop
    .bss_info_changed()
      disable fw beacon offload (skip this command)
    .stop_ap()
      set BSS to disconnected state (beacon offload disabled automatically)
      destroy BSS network resource

Fixes: 116c69603b01 ("mt76: mt7921: Add AP mode support")
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h

index a963e51..8c9b0f0 100644 (file)
@@ -1404,6 +1404,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
                else
                        conn_type = CONNECTION_INFRA_AP;
                basic_req.basic.conn_type = cpu_to_le32(conn_type);
+               /* Fully active/deactivate BSS network in AP mode only */
+               basic_req.basic.active = enable;
                break;
        case NL80211_IFTYPE_STATION:
                if (vif->p2p)
index 5163704..4be488d 100644 (file)
@@ -653,15 +653,6 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
                }
        }
 
-       if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
-               struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
-
-               mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
-                                           true);
-               mt7921_mcu_sta_update(dev, NULL, vif, true,
-                                     MT76_STA_INFO_STATE_NONE);
-       }
-
        if (changed & (BSS_CHANGED_BEACON |
                       BSS_CHANGED_BEACON_ENABLED))
                mt7921_mcu_uni_add_beacon_offload(dev, hw, vif,
@@ -1513,6 +1504,44 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw,
        mt7921_mutex_release(dev);
 }
 
+static int
+mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+               unsigned int link_id)
+{
+       struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+       struct mt7921_phy *phy = mt7921_hw_phy(hw);
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
+       int err;
+
+       err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
+                                         true);
+       if (err)
+               return err;
+
+       err = mt7921_mcu_set_bss_pm(dev, vif, true);
+       if (err)
+               return err;
+
+       return mt7921_mcu_sta_update(dev, NULL, vif, true,
+                                    MT76_STA_INFO_STATE_NONE);
+}
+
+static void
+mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+              unsigned int link_id)
+{
+       struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+       struct mt7921_phy *phy = mt7921_hw_phy(hw);
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
+       int err;
+
+       err = mt7921_mcu_set_bss_pm(dev, vif, false);
+       if (err)
+               return;
+
+       mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false);
+}
+
 const struct ieee80211_ops mt7921_ops = {
        .tx = mt7921_tx,
        .start = mt7921_start,
@@ -1523,6 +1552,8 @@ const struct ieee80211_ops mt7921_ops = {
        .conf_tx = mt7921_conf_tx,
        .configure_filter = mt7921_configure_filter,
        .bss_info_changed = mt7921_bss_info_changed,
+       .start_ap = mt7921_start_ap,
+       .stop_ap = mt7921_stop_ap,
        .sta_state = mt7921_sta_state,
        .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
        .set_key = mt7921_set_key,
index b8e5f55..bc434e6 100644 (file)
@@ -745,7 +745,7 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                                 &bcnft_req, sizeof(bcnft_req), true);
 }
 
-static int
+int
 mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                      bool enable)
 {
@@ -774,9 +774,6 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
        };
        int err;
 
-       if (vif->type != NL80211_IFTYPE_STATION)
-               return 0;
-
        err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),
                                &req_hdr, sizeof(req_hdr), false);
        if (err < 0 || !enable)
index 7da29fa..f7609c8 100644 (file)
@@ -284,6 +284,8 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force);
 int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev);
 void mt7921_dma_cleanup(struct mt7921_dev *dev);
 int mt7921_run_firmware(struct mt7921_dev *dev);
+int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
+                         bool enable);
 int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
                          struct ieee80211_vif *vif, bool enable,
                          enum mt76_sta_info_state state);