wifi: rtw89: update format of addr cam H2C command

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
This commit is contained in:
Chih-Kang Chang 2025-11-14 14:01:27 +08:00 committed by Ping-Ke Shih
parent fc2e8c873f
commit 9dab26b9fa
9 changed files with 56 additions and 22 deletions

View File

@ -236,7 +236,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
if (ret) if (ret)
rtw89_err(rtwdev, rtw89_err(rtwdev,
"failed to update dctl cam del key: %d\n", ret); "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) if (ret)
rtw89_err(rtwdev, "failed to update cam del key: %d\n", 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); ret);
return 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) { if (ret) {
rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
ret); 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, int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_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, struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link,
rtwsta_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_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link, struct rtw89_sta_link *rtwsta_link,
const u8 *scan_mac_addr, 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 ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_addr_cam_entry *addr_cam = struct rtw89_addr_cam_entry *addr_cam =

View File

@ -12,7 +12,7 @@
#define RTW89_BSSID_MATCH_ALL GENMASK(5, 0) #define RTW89_BSSID_MATCH_ALL GENMASK(5, 0)
#define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0) #define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0)
struct rtw89_h2c_addr_cam { struct rtw89_h2c_addr_cam_v0 {
__le32 w0; __le32 w0;
__le32 w1; __le32 w1;
__le32 w2; __le32 w2;
@ -30,6 +30,11 @@ struct rtw89_h2c_addr_cam {
__le32 w14; __le32 w14;
} __packed; } __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_IDX GENMASK(7, 0)
#define ADDR_CAM_W1_OFFSET GENMASK(15, 8) #define ADDR_CAM_W1_OFFSET GENMASK(15, 8)
#define ADDR_CAM_W1_LEN GENMASK(23, 16) #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_BSSID3 GENMASK(15, 8)
#define ADDR_CAM_W14_BSSID_BSSID4 GENMASK(23, 16) #define ADDR_CAM_W14_BSSID_BSSID4 GENMASK(23, 16)
#define ADDR_CAM_W14_BSSID_BSSID5 GENMASK(31, 24) #define ADDR_CAM_W14_BSSID_BSSID5 GENMASK(31, 24)
#define ADDR_CAM_W15_UPD_MODE GENMASK(2, 0)
struct rtw89_h2c_dctlinfo_ud_v1 { struct rtw89_h2c_dctlinfo_ud_v1 {
__le32 c0; __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_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link, struct rtw89_sta_link *rtwsta_link,
const u8 *scan_mac_addr, 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, void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_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, int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_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, int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,

View File

@ -4823,7 +4823,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
} }
/* update cam aid mac_id net_type */ /* 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) { if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n"); rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret; return ret;
@ -4897,7 +4898,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
} }
/* update cam aid mac_id net_type */ /* 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) { if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n"); rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret; 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_phy_config_edcca(rtwdev, bb, true);
rtw89_tas_scan(rtwdev, 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, 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(); 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_chip_rfk_scan(rtwdev, rtwvif_link, false);
rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx); rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx);

View File

@ -4678,6 +4678,7 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_RFK_NTFY_MCC_V0, RTW89_FW_FEATURE_RFK_NTFY_MCC_V0,
RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG, RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG,
RTW89_FW_FEATURE_BEACON_TRACKING, RTW89_FW_FEATURE_BEACON_TRACKING,
RTW89_FW_FEATURE_ADDR_CAM_V0,
}; };
struct rtw89_fw_suit { struct rtw89_fw_suit {

View 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, 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, 79, 0, CRASH_TRIGGER_TYPE_1),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING), __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, static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@ -2133,25 +2134,42 @@ void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
} }
int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, 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; struct rtw89_h2c_addr_cam *h2c;
u32 len = sizeof(*h2c); u32 len = sizeof(*h2c);
struct sk_buff *skb; struct sk_buff *skb;
u8 ver = U8_MAX;
int ret; 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); skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) { if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
return -ENOMEM; return -ENOMEM;
} }
skb_put(skb, len); 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, rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link,
scan_mac_addr, h2c); scan_mac_addr, h2c_v0);
rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, h2c); 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, rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CAT_MAC,
H2C_CL_MAC_ADDR_CAM_UPDATE, H2C_CL_MAC_ADDR_CAM_UPDATE,

View File

@ -4887,7 +4887,8 @@ int rtw89_fw_h2c_tbtt_tuning(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, u32 offset); 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_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, 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, int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link); struct rtw89_sta_link *rtwsta_link);

View File

@ -4835,7 +4835,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
if (ret) if (ret)
return 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) if (ret)
return 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); 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) if (ret)
return ret; return ret;

View File

@ -759,7 +759,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) { if (changed & BSS_CHANGED_BSSID) {
ether_addr_copy(rtwvif_link->bssid, conf->bssid); ether_addr_copy(rtwvif_link->bssid, conf->bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif_link); 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); 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_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_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE);
rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); 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); rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) { if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) {

View 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) { if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n"); rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret; return ret;
@ -1318,7 +1319,8 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
return 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_FW_RESTORE);
if (ret) { if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n"); rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret; return ret;