mt76: mt7921: enable deep sleep at runtime
authorSean Wang <sean.wang@mediatek.com>
Mon, 10 May 2021 15:14:52 +0000 (23:14 +0800)
committerFelix Fietkau <nbd@nbd.name>
Sat, 19 Jun 2021 07:22:50 +0000 (09:22 +0200)
Enable the deep sleep mode with that firmware is able to trap into
the doze state at runtime to reduce the power consumption further.

The deep sleep mode is not allowed in the STA state transition with
the firmware to have the fast connection experience as we've done in
the full power mode

Reviewed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/init.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
drivers/net/wireless/mediatek/mt76/mt7921/pci.c

index ea1f23e..f8a0969 100644 (file)
@@ -1028,9 +1028,10 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
        if (IS_ERR(sskb))
                return PTR_ERR(sskb);
 
-       mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable);
+       mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true);
        if (enable && sta)
-               mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0);
+               mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
+                                       MT76_STA_INFO_STATE_ASSOC);
 
        wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
                                                  WTBL_RESET_AND_SET, NULL,
@@ -1157,11 +1158,12 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
                .vif = vif,
                .offload_fw = offload_fw,
                .enable = enable,
+               .newly = true,
                .cmd = cmd,
        };
 
        info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
-       return mt76_connac_mcu_add_sta_cmd(phy, &info);
+       return mt76_connac_mcu_sta_cmd(phy, &info);
 }
 
 static int
index 78498d8..302318e 100644 (file)
@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req);
 void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
                                   struct ieee80211_vif *vif,
                                   struct ieee80211_sta *sta,
-                                  bool enable)
+                                  bool enable, bool newly)
 {
        struct sta_rec_basic *basic;
        struct tlv *tlv;
@@ -316,7 +316,8 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
        basic->extra_info = cpu_to_le16(EXTRA_INFO_VER);
 
        if (enable) {
-               basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
+               if (newly)
+                       basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
                basic->conn_state = CONN_STATE_PORT_SECURE;
        } else {
                basic->conn_state = CONN_STATE_DISCONNECT;
@@ -709,7 +710,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
                             struct ieee80211_sta *sta,
                             struct ieee80211_vif *vif,
-                            u8 rcpi)
+                            u8 rcpi, u8 sta_state)
 {
        struct cfg80211_chan_def *chandef = &mphy->chandef;
        enum nl80211_band band = chandef->chan->band;
@@ -774,7 +775,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
 
        tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state));
        state = (struct sta_rec_state *)tlv;
-       state->state = 2;
+       state->state = sta_state;
 
        if (sta->vht_cap.vht_supported) {
                state->vht_opmode = sta->bandwidth;
@@ -866,8 +867,8 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);
 
-int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-                               struct mt76_sta_cmd_info *info)
+int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
+                           struct mt76_sta_cmd_info *info)
 {
        struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
        struct mt76_dev *dev = phy->dev;
@@ -881,10 +882,11 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
 
        if (info->sta || !info->offload_fw)
                mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta,
-                                             info->enable);
+                                             info->enable, info->newly);
        if (info->sta && info->enable)
                mt76_connac_mcu_sta_tlv(phy, skb, info->sta,
-                                       info->vif, info->rcpi);
+                                       info->vif, info->rcpi,
+                                       info->state);
 
        sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
                                           sizeof(struct tlv));
@@ -908,7 +910,7 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
 
        return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
 }
-EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd);
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_cmd);
 
 void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                 struct ieee80211_ampdu_params *params,
@@ -1616,6 +1618,26 @@ int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable)
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_deep_sleep);
 
+int mt76_connac_sta_state_dp(struct mt76_dev *dev,
+                            enum ieee80211_sta_state old_state,
+                            enum ieee80211_sta_state new_state)
+{
+       if ((old_state == IEEE80211_STA_ASSOC &&
+            new_state == IEEE80211_STA_AUTHORIZED) ||
+           (old_state == IEEE80211_STA_NONE &&
+            new_state == IEEE80211_STA_NOTEXIST))
+               mt76_connac_mcu_set_deep_sleep(dev, true);
+
+       if ((old_state == IEEE80211_STA_NOTEXIST &&
+            new_state == IEEE80211_STA_NONE) ||
+           (old_state == IEEE80211_STA_AUTHORIZED &&
+            new_state == IEEE80211_STA_ASSOC))
+               mt76_connac_mcu_set_deep_sleep(dev, false);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_connac_sta_state_dp);
+
 void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
                                    struct mt76_connac_coredump *coredump)
 {
index 9f3c879..1c73beb 100644 (file)
@@ -927,6 +927,12 @@ struct mt76_connac_suspend_tlv {
        u8 pad[5];
 } __packed;
 
+enum mt76_sta_info_state {
+       MT76_STA_INFO_STATE_NONE,
+       MT76_STA_INFO_STATE_AUTH,
+       MT76_STA_INFO_STATE_ASSOC
+};
+
 struct mt76_sta_cmd_info {
        struct ieee80211_sta *sta;
        struct mt76_wcid *wcid;
@@ -935,8 +941,10 @@ struct mt76_sta_cmd_info {
 
        bool offload_fw;
        bool enable;
+       bool newly;
        int cmd;
        u8 rcpi;
+       u8 state;
 };
 
 #define MT_SKU_POWER_LIMIT     161
@@ -1006,7 +1014,8 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
 int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
 void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
                                   struct ieee80211_vif *vif,
-                                  struct ieee80211_sta *sta, bool enable);
+                                  struct ieee80211_sta *sta, bool enable,
+                                  bool newly);
 void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                      struct ieee80211_vif *vif,
                                      struct ieee80211_sta *sta, void *sta_wtbl,
@@ -1021,7 +1030,7 @@ int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
 void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
                             struct ieee80211_sta *sta,
                             struct ieee80211_vif *vif,
-                            u8 rcpi);
+                            u8 rcpi, u8 state);
 void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                 struct ieee80211_sta *sta, void *sta_wtbl,
                                 void *wtbl_tlv);
@@ -1043,8 +1052,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
                                struct ieee80211_vif *vif,
                                struct mt76_wcid *wcid,
                                bool enable);
-int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-                               struct mt76_sta_cmd_info *info);
+int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
+                           struct mt76_sta_cmd_info *info);
 void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
                                      struct ieee80211_vif *vif);
 int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);
@@ -1076,6 +1085,9 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
 int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
 void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
                                      struct ieee80211_vif *vif);
+int mt76_connac_sta_state_dp(struct mt76_dev *dev,
+                            enum ieee80211_sta_state old_state,
+                            enum ieee80211_sta_state new_state);
 int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
 int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
 void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
index b399f3b..aca057c 100644 (file)
@@ -231,7 +231,11 @@ int mt7921_register_device(struct mt7921_dev *dev)
        if (ret)
                return ret;
 
-       return mt7921_init_debugfs(dev);
+       ret = mt7921_init_debugfs(dev);
+       if (ret)
+               return ret;
+
+       return mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.enable);
 }
 
 void mt7921_unregister_device(struct mt7921_dev *dev)
index 5fc6cf7..07e86ba 100644 (file)
@@ -577,7 +577,8 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
                mt7921_mcu_uni_bss_ps(dev, vif);
 
        if (changed & BSS_CHANGED_ASSOC) {
-               mt7921_mcu_sta_add(dev, NULL, vif, true);
+               mt7921_mcu_sta_update(dev, NULL, vif, true,
+                                     MT76_STA_INFO_STATE_ASSOC);
                mt7921_bss_bcnft_apply(dev, vif, info->assoc);
        }
 
@@ -616,17 +617,14 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        if (ret)
                return ret;
 
-       if (vif->type == NL80211_IFTYPE_STATION) {
+       if (vif->type == NL80211_IFTYPE_STATION)
                mvif->wep_sta = msta;
-               if (!sta->tdls)
-                       mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
-                                                   &mvif->sta.wcid, true);
-       }
 
        mt7921_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
-       ret = mt7921_mcu_sta_add(dev, sta, vif, true);
+       ret = mt7921_mcu_sta_update(dev, sta, vif, true,
+                                   MT76_STA_INFO_STATE_NONE);
        if (ret)
                return ret;
 
@@ -635,6 +633,27 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        return 0;
 }
 
+void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+                         struct ieee80211_sta *sta)
+{
+       struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
+       struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+
+       mt7921_mutex_acquire(dev);
+
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+               mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
+                                           true);
+
+       mt7921_mac_wtbl_update(dev, msta->wcid.idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+
+       mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC);
+
+       mt7921_mutex_release(dev);
+}
+
 void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta)
 {
@@ -644,7 +663,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
        mt76_connac_pm_wake(&dev->mphy, &dev->pm);
 
-       mt7921_mcu_sta_add(dev, sta, vif, false);
+       mt7921_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE);
        mt7921_mac_wtbl_update(dev, msta->wcid.idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -790,20 +809,21 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        return ret;
 }
 
-static int
-mt7921_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-              struct ieee80211_sta *sta)
+static int mt7921_sta_state(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif,
+                           struct ieee80211_sta *sta,
+                           enum ieee80211_sta_state old_state,
+                           enum ieee80211_sta_state new_state)
 {
-       return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
-                             IEEE80211_STA_NONE);
-}
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
 
-static int
-mt7921_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                 struct ieee80211_sta *sta)
-{
-       return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
-                             IEEE80211_STA_NOTEXIST);
+       if (dev->pm.enable) {
+               mt7921_mutex_acquire(dev);
+               mt76_connac_sta_state_dp(&dev->mt76, old_state, new_state);
+               mt7921_mutex_release(dev);
+       }
+
+       return mt76_sta_state(hw, vif, sta, old_state, new_state);
 }
 
 static int
@@ -1149,8 +1169,7 @@ const struct ieee80211_ops mt7921_ops = {
        .conf_tx = mt7921_conf_tx,
        .configure_filter = mt7921_configure_filter,
        .bss_info_changed = mt7921_bss_info_changed,
-       .sta_add = mt7921_sta_add,
-       .sta_remove = mt7921_sta_remove,
+       .sta_state = mt7921_sta_state,
        .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
        .set_key = mt7921_set_key,
        .sta_set_decap_offload = mt7921_sta_set_decap_offload,
index ca481e3..23ec0c8 100644 (file)
@@ -1267,8 +1267,9 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                                 sizeof(req), false);
 }
 
-int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-                      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)
 {
        struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
        int rssi = -ewma_rssi_read(&mvif->rssi);
@@ -1277,6 +1278,7 @@ int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
                .vif = vif,
                .enable = enable,
                .cmd = MCU_UNI_CMD_STA_REC_UPDATE,
+               .state = state,
                .offload_fw = true,
                .rcpi = to_rcpi(rssi),
        };
@@ -1284,8 +1286,9 @@ int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
 
        msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL;
        info.wcid = msta ? &msta->wcid : &mvif->sta.wcid;
+       info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;
 
-       return mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
+       return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);
 }
 
 int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
index a6ff704..92cf384 100644 (file)
@@ -261,8 +261,9 @@ int mt7921_mcu_init(struct mt7921_dev *dev);
 int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                       struct mt7921_sta *msta, struct ieee80211_key_conf *key,
                       enum set_key_cmd cmd);
-int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-                      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);
 int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd);
 int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif);
 int mt7921_mcu_set_eeprom(struct mt7921_dev *dev);
@@ -334,6 +335,8 @@ void mt7921_mac_fill_rx_vector(struct mt7921_dev *dev, struct sk_buff *skb);
 void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb);
 int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
+void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+                         struct ieee80211_sta *sta);
 void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta);
 void mt7921_mac_work(struct work_struct *work);
index 13263f5..27906b2 100644 (file)
@@ -106,6 +106,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
                .rx_poll_complete = mt7921_rx_poll_complete,
                .sta_ps = mt7921_sta_ps,
                .sta_add = mt7921_mac_sta_add,
+               .sta_assoc = mt7921_mac_sta_assoc,
                .sta_remove = mt7921_mac_sta_remove,
                .update_survey = mt7921_update_channel,
        };