wifi: rtw89: refine packet offload flow
authorChin-Yen Lee <timlee@realtek.com>
Mon, 23 Jan 2023 06:53:57 +0000 (14:53 +0800)
committerKalle Valo <kvalo@kernel.org>
Mon, 13 Feb 2023 17:17:35 +0000 (19:17 +0200)
For upcoming firmware, driver needs to do packet offload to firmware to
ensure LPS protocol work properly, so we update current connection and
disconnect flow to maintain packet offload flow, and integrate with
current WoWLAN flow which also needs packet offload.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230123065401.14174-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac80211.c
drivers/net/wireless/realtek/rtw89/ser.c
drivers/net/wireless/realtek/rtw89/wow.c

index 23550e193976d96fafff024cd18f73d03975ec19..78ce64d1a387d2e716f73167b62bdb31a12a4424 100644 (file)
@@ -2495,8 +2495,10 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
        if (sta->tdls)
                rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);
 
-       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
                rtw89_vif_type_mapping(vif, false);
+               rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, true);
+       }
 
        ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
        if (ret) {
@@ -2584,12 +2586,6 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
                return ret;
        }
 
-       ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwsta->mac_id);
-       if (ret) {
-               rtw89_warn(rtwdev, "failed to send h2c general packet\n");
-               return ret;
-       }
-
        rtwdev->total_sta_assoc++;
        if (sta->tdls)
                rtwvif->tdls_peer++;
@@ -2608,6 +2604,12 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
                                         BTC_ROLE_MSTS_STA_CONN_END);
                rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template);
                rtw89_phy_ul_tb_assoc(rtwdev, rtwvif);
+
+               ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
+               if (ret) {
+                       rtw89_warn(rtwdev, "failed to send h2c general packet\n");
+                       return ret;
+               }
        }
 
        return ret;
@@ -3132,7 +3134,6 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
                        continue;
                INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]);
        }
-       INIT_LIST_HEAD(&rtwdev->wow.pkt_list);
        INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work);
        INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work);
        INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work);
index a762eef699fa081a6c59ff0e46d59950c26c91e1..505e3b20436ac00232360ba5821183b9cb221095 100644 (file)
@@ -2461,6 +2461,7 @@ struct rtw89_vif {
        struct rtw89_phy_rate_pattern rate_pattern;
        struct cfg80211_scan_request *scan_req;
        struct ieee80211_scan_ies *scan_ies;
+       struct list_head general_pkt_list;
 };
 
 enum rtw89_lv1_rcvy_step {
@@ -3724,7 +3725,6 @@ struct rtw89_wow_param {
        DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM);
        struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM];
        u8 pattern_cnt;
-       struct list_head pkt_list;
 };
 
 struct rtw89_mcc_info {
index 210785149801b02f6be504699949bf9e515fb17e..dc90074261244ce783e448af0b09e368a77a35aa 100644 (file)
@@ -10,6 +10,7 @@
 #include "mac.h"
 #include "phy.h"
 #include "reg.h"
+#include "util.h"
 
 static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
                                    struct sk_buff *skb);
@@ -913,13 +914,12 @@ fail:
        return ret;
 }
 
-static int rtw89_fw_h2c_add_wow_fw_ofld(struct rtw89_dev *rtwdev,
+static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
                                        struct rtw89_vif *rtwvif,
                                        enum rtw89_fw_pkt_ofld_type type,
                                        u8 *id)
 {
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
-       struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
        struct rtw89_pktofld_info *info;
        struct sk_buff *skb;
        int ret;
@@ -954,7 +954,7 @@ static int rtw89_fw_h2c_add_wow_fw_ofld(struct rtw89_dev *rtwdev,
        if (ret)
                goto err;
 
-       list_add_tail(&info->list, &rtw_wow->pkt_list);
+       list_add_tail(&info->list, &rtwvif->general_pkt_list);
        *id = info->id;
        return 0;
 
@@ -963,13 +963,48 @@ err:
        return -ENOMEM;
 }
 
+void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
+                                          struct rtw89_vif *rtwvif, bool notify_fw)
+{
+       struct list_head *pkt_list = &rtwvif->general_pkt_list;
+       struct rtw89_pktofld_info *info, *tmp;
+
+       list_for_each_entry_safe(info, tmp, pkt_list, list) {
+               if (notify_fw)
+                       rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+               rtw89_core_release_bit_map(rtwdev->pkt_offload,
+                                          info->id);
+               list_del(&info->list);
+               kfree(info);
+       }
+}
+
+void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw)
+{
+       struct rtw89_vif *rtwvif;
+
+       rtw89_for_each_rtwvif(rtwdev, rtwvif)
+               rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw);
+}
+
 #define H2C_GENERAL_PKT_LEN 6
 #define H2C_GENERAL_PKT_ID_UND 0xff
-int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid)
+int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev,
+                            struct rtw89_vif *rtwvif, u8 macid)
 {
+       u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND;
+       u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND;
+       u8 pkt_id_qos_null = H2C_GENERAL_PKT_ID_UND;
        struct sk_buff *skb;
        int ret;
 
+       rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+                                    RTW89_PKT_OFLD_TYPE_PS_POLL, &pkt_id_ps_poll);
+       rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+                                    RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id_null);
+       rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+                                    RTW89_PKT_OFLD_TYPE_QOS_NULL, &pkt_id_qos_null);
+
        skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN);
        if (!skb) {
                rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
@@ -978,9 +1013,9 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid)
        skb_put(skb, H2C_GENERAL_PKT_LEN);
        SET_GENERAL_PKT_MACID(skb->data, macid);
        SET_GENERAL_PKT_PROBRSP_ID(skb->data, H2C_GENERAL_PKT_ID_UND);
-       SET_GENERAL_PKT_PSPOLL_ID(skb->data, H2C_GENERAL_PKT_ID_UND);
-       SET_GENERAL_PKT_NULL_ID(skb->data, H2C_GENERAL_PKT_ID_UND);
-       SET_GENERAL_PKT_QOS_NULL_ID(skb->data, H2C_GENERAL_PKT_ID_UND);
+       SET_GENERAL_PKT_PSPOLL_ID(skb->data, pkt_id_ps_poll);
+       SET_GENERAL_PKT_NULL_ID(skb->data, pkt_id_null);
+       SET_GENERAL_PKT_QOS_NULL_ID(skb->data, pkt_id_qos_null);
        SET_GENERAL_PKT_CTS2SELF_ID(skb->data, H2C_GENERAL_PKT_ID_UND);
 
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -3099,8 +3134,9 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
        int ret;
 
        if (enable) {
-               ret = rtw89_fw_h2c_add_wow_fw_ofld(rtwdev, rtwvif,
-                                                  RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id);
+               ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+                                                  RTW89_PKT_OFLD_TYPE_NULL_DATA,
+                                                  &pkt_id);
                if (ret)
                        return -EPERM;
        }
index 6cb578201b2a828637508dab807c608c99e885e2..cae07e325326df742e171e3fcfe22478fe59e47f 100644 (file)
@@ -3518,7 +3518,11 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
 int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len);
 void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev);
 void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev);
-int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid);
+int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+                            u8 macid);
+void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
+                                          struct rtw89_vif *rtwvif, bool notify_fw);
+void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw);
 int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
                        bool valid, struct ieee80211_ampdu_params *params);
 void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev);
index f9b95c52916bb0ffcb88be4635bfdf2786995aa6..d43281f7335b139c636f2fd6fabf2a0245384839 100644 (file)
@@ -135,6 +135,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
        rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
        rtwvif->hit_rule = 0;
        ether_addr_copy(rtwvif->mac_addr, vif->addr);
+       INIT_LIST_HEAD(&rtwvif->general_pkt_list);
 
        ret = rtw89_mac_add_vif(rtwdev, rtwvif);
        if (ret) {
index c1a4bc1c64d16fba26f642c0a43118a66182ab12..61db7189fdab8df6aa955faa65128af9f89c395b 100644 (file)
@@ -611,6 +611,7 @@ bottom:
        ser_reset_mac_binding(rtwdev);
        rtw89_core_stop(rtwdev);
        rtw89_entity_init(rtwdev);
+       rtw89_fw_release_general_pkt_list(rtwdev, false);
        INIT_LIST_HEAD(&rtwdev->rtwvifs_list);
 }
 
index b2b826b2e09aeaad49c2b35584ec133e242f002c..92fa366ccfcf7f8deb4ea522915454d8b31ccfca 100644 (file)
@@ -490,21 +490,6 @@ static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable)
        return ret;
 }
 
-static void rtw89_wow_release_pkt_list(struct rtw89_dev *rtwdev)
-{
-       struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-       struct list_head *pkt_list = &rtw_wow->pkt_list;
-       struct rtw89_pktofld_info *info, *tmp;
-
-       list_for_each_entry_safe(info, tmp, pkt_list, list) {
-               rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
-               rtw89_core_release_bit_map(rtwdev->pkt_offload,
-                                          info->id);
-               list_del(&info->list);
-               kfree(info);
-       }
-}
-
 static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
 {
        enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL;
@@ -561,6 +546,11 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
        }
 
        if (is_conn) {
+               ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
+               if (ret) {
+                       rtw89_warn(rtwdev, "failed to send h2c general packet\n");
+                       return ret;
+               }
                rtw89_phy_ra_assoc(rtwdev, wow_sta);
                rtw89_phy_set_bss_color(rtwdev, wow_vif);
                rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif);
@@ -708,8 +698,6 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
                goto out;
        }
 
-       rtw89_wow_release_pkt_list(rtwdev);
-
        ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false);
        if (ret) {
                rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n");
@@ -744,6 +732,8 @@ static int rtw89_wow_enable(struct rtw89_dev *rtwdev)
                goto out;
        }
 
+       rtw89_fw_release_general_pkt_list(rtwdev, true);
+
        ret = rtw89_wow_swap_fw(rtwdev, true);
        if (ret) {
                rtw89_err(rtwdev, "wow: failed to swap to wow fw\n");
@@ -789,6 +779,8 @@ static int rtw89_wow_disable(struct rtw89_dev *rtwdev)
                goto out;
        }
 
+       rtw89_fw_release_general_pkt_list(rtwdev, true);
+
        ret = rtw89_wow_swap_fw(rtwdev, false);
        if (ret) {
                rtw89_err(rtwdev, "wow: failed to disable trx_post\n");