]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: update format of addr cam H2C command
authorChih-Kang Chang <gary.chang@realtek.com>
Fri, 14 Nov 2025 06:01:27 +0000 (14:01 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Tue, 18 Nov 2025 01:28:42 +0000 (09:28 +0800)
The addr cam H2C command is to tell firmware the addr related info.
For RTL8922D and RTL8922A after firmware version 0.35.84.0, the addr cam
must be updated with update mode to avoid clearing previously set
fields. Update it accordingly.

Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20251114060128.35363-14-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/cam.c
drivers/net/wireless/realtek/rtw89/cam.h
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/mac.c
drivers/net/wireless/realtek/rtw89/mac80211.c
drivers/net/wireless/realtek/rtw89/wow.c

index 5f282a02a3564ca7fd149076c9c6f5ea07750205..9370cbda945c0de17fe7e8633ef2ffcecf24341a 100644 (file)
@@ -236,7 +236,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
                if (ret)
                        rtw89_err(rtwdev,
                                  "failed to update dctl cam del key: %d\n", ret);
-               ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+               ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                                      RTW89_ROLE_INFO_CHANGE);
                if (ret)
                        rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
        }
@@ -276,7 +277,8 @@ static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
                          ret);
                return ret;
        }
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                              RTW89_ROLE_INFO_CHANGE);
        if (ret) {
                rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
                          ret);
@@ -761,7 +763,7 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
 int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
                                  struct rtw89_vif_link *rtwvif_link,
                                  struct rtw89_sta_link *rtwsta_link,
-                                 struct rtw89_h2c_addr_cam *h2c)
+                                 struct rtw89_h2c_addr_cam_v0 *h2c)
 {
        struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link,
                                                                         rtwsta_link);
@@ -813,7 +815,7 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
                                  struct rtw89_vif_link *rtwvif_link,
                                  struct rtw89_sta_link *rtwsta_link,
                                  const u8 *scan_mac_addr,
-                                 struct rtw89_h2c_addr_cam *h2c)
+                                 struct rtw89_h2c_addr_cam_v0 *h2c)
 {
        struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
        struct rtw89_addr_cam_entry *addr_cam =
index 833a956f0176ca8553ea5be968575460b47496ee..c46b6f91bbdb12ffeb368b7a37b829c5176382ea 100644 (file)
@@ -12,7 +12,7 @@
 #define RTW89_BSSID_MATCH_ALL GENMASK(5, 0)
 #define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0)
 
-struct rtw89_h2c_addr_cam {
+struct rtw89_h2c_addr_cam_v0 {
        __le32 w0;
        __le32 w1;
        __le32 w2;
@@ -30,6 +30,11 @@ struct rtw89_h2c_addr_cam {
        __le32 w14;
 } __packed;
 
+struct rtw89_h2c_addr_cam {
+       struct rtw89_h2c_addr_cam_v0 v0;
+       __le32 w15;
+} __packed;
+
 #define ADDR_CAM_W1_IDX GENMASK(7, 0)
 #define ADDR_CAM_W1_OFFSET GENMASK(15, 8)
 #define ADDR_CAM_W1_LEN GENMASK(23, 16)
@@ -109,6 +114,7 @@ struct rtw89_h2c_addr_cam {
 #define ADDR_CAM_W14_BSSID_BSSID3 GENMASK(15, 8)
 #define ADDR_CAM_W14_BSSID_BSSID4 GENMASK(23, 16)
 #define ADDR_CAM_W14_BSSID_BSSID5 GENMASK(31, 24)
+#define ADDR_CAM_W15_UPD_MODE GENMASK(2, 0)
 
 struct rtw89_h2c_dctlinfo_ud_v1 {
        __le32 c0;
@@ -313,7 +319,7 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
                                  struct rtw89_vif_link *rtwvif_link,
                                  struct rtw89_sta_link *rtwsta_link,
                                  const u8 *scan_mac_addr,
-                                 struct rtw89_h2c_addr_cam *h2c);
+                                 struct rtw89_h2c_addr_cam_v0 *h2c);
 void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
                                         struct rtw89_vif_link *rtwvif_link,
                                         struct rtw89_sta_link *rtwsta_link,
@@ -325,7 +331,7 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
 int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
                                  struct rtw89_vif_link *rtwvif_link,
                                  struct rtw89_sta_link *rtwsta_link,
-                                 struct rtw89_h2c_addr_cam *h2c);
+                                 struct rtw89_h2c_addr_cam_v0 *h2c);
 int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
                          struct ieee80211_vif *vif,
                          struct ieee80211_sta *sta,
index ea22925b8772dace5257c8ed179247a89e581ec8..a14edc321ca7bf67f9dc3f04185db648aa3a1ce1 100644 (file)
@@ -4823,7 +4823,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
        }
 
        /* update cam aid mac_id net_type */
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                              RTW89_ROLE_CON_DISCONN);
        if (ret) {
                rtw89_warn(rtwdev, "failed to send h2c cam\n");
                return ret;
@@ -4897,7 +4898,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
        }
 
        /* update cam aid mac_id net_type */
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                              RTW89_ROLE_CON_DISCONN);
        if (ret) {
                rtw89_warn(rtwdev, "failed to send h2c cam\n");
                return ret;
@@ -6029,7 +6031,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
        rtw89_phy_config_edcca(rtwdev, bb, true);
        rtw89_tas_scan(rtwdev, true);
 
-       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr);
+       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr,
+                        RTW89_ROLE_INFO_CHANGE);
 }
 
 void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
@@ -6049,7 +6052,8 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
 
        rcu_read_unlock();
 
-       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL,
+                        RTW89_ROLE_INFO_CHANGE);
 
        rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false);
        rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx);
index c33ff7c0090fe32b9012e2fa7df918895fc4bb3f..ab71489b89a33cb6c4886de276a8f0c8b7cf5c47 100644 (file)
@@ -4678,6 +4678,7 @@ enum rtw89_fw_feature {
        RTW89_FW_FEATURE_RFK_NTFY_MCC_V0,
        RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG,
        RTW89_FW_FEATURE_BEACON_TRACKING,
+       RTW89_FW_FEATURE_ADDR_CAM_V0,
 };
 
 struct rtw89_fw_suit {
index 9f132a469629daa9906e9a7f64c96593c350c392..18eab404885c1b7051b6a91e892f05b88acfed30 100644 (file)
@@ -881,6 +881,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
        __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG),
        __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1),
        __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING),
+       __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0),
 };
 
 static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -2133,25 +2134,42 @@ plain_log:
 }
 
 int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
-                    struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr)
+                    struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr,
+                    enum rtw89_upd_mode upd_mode)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       struct rtw89_h2c_addr_cam_v0 *h2c_v0;
        struct rtw89_h2c_addr_cam *h2c;
        u32 len = sizeof(*h2c);
        struct sk_buff *skb;
+       u8 ver = U8_MAX;
        int ret;
 
+       if (RTW89_CHK_FW_FEATURE(ADDR_CAM_V0, &rtwdev->fw) ||
+           chip->chip_gen == RTW89_CHIP_AX) {
+               len = sizeof(*h2c_v0);
+               ver = 0;
+       }
+
        skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
        if (!skb) {
                rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
                return -ENOMEM;
        }
        skb_put(skb, len);
-       h2c = (struct rtw89_h2c_addr_cam *)skb->data;
+       h2c_v0 = (struct rtw89_h2c_addr_cam_v0 *)skb->data;
 
        rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link,
-                                    scan_mac_addr, h2c);
-       rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, h2c);
+                                    scan_mac_addr, h2c_v0);
+       rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, h2c_v0);
 
+       if (ver == 0)
+               goto hdr;
+
+       h2c = (struct rtw89_h2c_addr_cam *)skb->data;
+       h2c->w15 = le32_encode_bits(upd_mode, ADDR_CAM_W15_UPD_MODE);
+
+hdr:
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
                              H2C_CAT_MAC,
                              H2C_CL_MAC_ADDR_CAM_UPDATE,
index e62b61f584fbd28cf65d61697cc976edac0b19e0..cedb4a47a769cf76efa8b3e907f7d57eec36f6b3 100644 (file)
@@ -4887,7 +4887,8 @@ int rtw89_fw_h2c_tbtt_tuning(struct rtw89_dev *rtwdev,
                             struct rtw89_vif_link *rtwvif_link, u32 offset);
 int rtw89_fw_h2c_pwr_lvl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
 int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif,
-                    struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr);
+                    struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr,
+                    enum rtw89_upd_mode upd_mode);
 int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
                                 struct rtw89_vif_link *rtwvif_link,
                                 struct rtw89_sta_link *rtwsta_link);
index 386cc982d7c9101aa59466b8a0285ade741b17dd..bde3791dd3309a10c13f58df72e75a0673576978 100644 (file)
@@ -4835,7 +4835,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
        if (ret)
                return ret;
 
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_CREATE);
        if (ret)
                return ret;
 
@@ -4860,7 +4860,7 @@ int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif
 
        rtw89_cam_deinit(rtwdev, rtwvif_link);
 
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_REMOVE);
        if (ret)
                return ret;
 
index 4a7364432428be0dc371474077ff289c12ccad9b..82598673ddec544dc8a0d539b8e705b2001fb700 100644 (file)
@@ -759,7 +759,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
        if (changed & BSS_CHANGED_BSSID) {
                ether_addr_copy(rtwvif_link->bssid, conf->bssid);
                rtw89_cam_bssid_changed(rtwdev, rtwvif_link);
-               rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+               rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_INFO_CHANGE);
                WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0);
        }
 
@@ -818,7 +818,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
        rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL);
        rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE);
        rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
-       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+       rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_TYPE_CHANGE);
        rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
 
        if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) {
index b9fce0be3ab702fc9c017a6eeded46dd353b6454..46aba4cb2ee9e5059fb043e4d979e11da077b80f 100644 (file)
@@ -1221,7 +1221,8 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
                }
        }
 
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                              RTW89_ROLE_INFO_CHANGE);
        if (ret) {
                rtw89_warn(rtwdev, "failed to send h2c cam\n");
                return ret;
@@ -1318,7 +1319,8 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
                return ret;
        }
 
-       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
+       ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL,
+                              RTW89_ROLE_FW_RESTORE);
        if (ret) {
                rtw89_warn(rtwdev, "failed to send h2c cam\n");
                return ret;