From: Zong-Zhe Yang Previously each link took one BA CAM entry, and then when a MLD (MLSR) switches the target link, the relation between old link and old BA CAM entry got missing and could not correctly release the old BA CAM entry. Besides, it would cause list_del corruption problems once BA CAM entry replacing process was activated after all BA CAM entries were leaked. Since HW supports to use single BA CAM entry per MLD, no need to maintain multiple BA CAM entries across different links. So, set MLD_EN bit when a MLD acquire a BA CAM entry and tweak the flow correspondingly. Reported-by: Aiden Calloway Closes: https://lore.kernel.org/linux-wireless/CAH-fA9oS2N-D05BSd0DDp_hGtBEH==cLuxr1XCUiL_UC3CN+bg@mail.gmail.com/ Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 9 ++- drivers/net/wireless/realtek/rtw89/core.h | 11 ++-- drivers/net/wireless/realtek/rtw89/debug.c | 7 ++- drivers/net/wireless/realtek/rtw89/fw.c | 61 +++++++++++++------ drivers/net/wireless/realtek/rtw89/fw.h | 26 ++------ drivers/net/wireless/realtek/rtw89/mac80211.c | 2 + drivers/net/wireless/realtek/rtw89/ser.c | 4 +- 7 files changed, 64 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index b074b3677c43..0c1c5c8ae8ce 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -5601,7 +5601,7 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits) } int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta_link *rtwsta_link, u8 tid, + struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -5639,7 +5639,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, } entry->tid = tid; - list_add_tail(&entry->list, &rtwsta_link->ba_cam_list); + list_add_tail(&entry->list, &rtwsta->ba_cam_list); *cam_idx = idx; @@ -5647,7 +5647,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, } int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta_link *rtwsta_link, u8 tid, + struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) { struct rtw89_cam_info *cam_info = &rtwdev->cam_info; @@ -5656,7 +5656,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, lockdep_assert_wiphy(rtwdev->hw->wiphy); - list_for_each_entry_safe(entry, tmp, &rtwsta_link->ba_cam_list, list) { + list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) { if (entry->tid != tid) continue; @@ -5751,7 +5751,6 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, int ret; rtwsta_link->prev_rssi = 0; - INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); ewma_rssi_init(&rtwsta_link->avg_rssi); ewma_snr_init(&rtwsta_link->avg_snr); ewma_evm_init(&rtwsta_link->evm_1ss); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 2e6d1be3a751..db1a8179e597 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -4638,7 +4638,6 @@ struct rtw89_sta_link { __le32 htc_template; struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */ struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */ - struct list_head ba_cam_list; bool use_cfg_mask; struct cfg80211_bitrate_mask mask; @@ -4989,9 +4988,7 @@ struct rtw89_chip_ops { struct rtw89_sta_link *rtwsta_link); int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); - int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, + int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params); int (*h2c_wow_cam_update)(struct rtw89_dev *rtwdev, struct rtw89_wow_cam_info *cam_info); @@ -7778,6 +7775,8 @@ struct rtw89_sta { struct rtw89_tid_stats tid_rx_stats[IEEE80211_NUM_TIDS]; DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); + struct list_head ba_cam_list; + DECLARE_BITMAP(pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM); struct list_head dlink_pool; @@ -9339,10 +9338,10 @@ u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size); void rtw89_core_release_bit_map(unsigned long *addr, u8 bit); void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits); int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta_link *rtwsta_link, u8 tid, + struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta_link *rtwsta_link, u8 tid, + struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 2417381bca1c..3a430bd082c3 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -4642,13 +4642,13 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) static int rtw89_dump_ba_cam(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, - struct rtw89_sta_link *rtwsta_link) + struct rtw89_sta *rtwsta) { struct rtw89_ba_cam_entry *entry; char *p = buf, *end = buf + bufsz; bool first = true; - list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) { + list_for_each_entry(entry, &rtwsta->ba_cam_list, list) { if (first) { p += scnprintf(p, end - p, "\tba_cam "); first = false; @@ -4683,7 +4683,6 @@ static int rtw89_sta_link_ids_get(struct rtw89_dev *rtwdev, p += scnprintf(p, end - p, "\tlink_id=%u%s\n", rtwsta_link->link_id, designated ? " (*)" : ""); p += rtw89_dump_addr_cam(rtwdev, p, end - p, &rtwsta_link->addr_cam); - p += rtw89_dump_ba_cam(rtwdev, p, end - p, rtwsta_link); return p - buf; } @@ -4705,6 +4704,8 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) p += scnprintf(p, end - p, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : ""); + p += rtw89_dump_ba_cam(rtwdev, p, end - p, rtwsta); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) p += rtw89_sta_link_ids_get(rtwdev, p, end - p, rtwsta_link, rtwsta_link == designated_link); diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 63dd918b0989..fa30543a8b42 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2606,23 +2606,28 @@ int rtw89_fw_h2c_default_dmac_tbl_v3(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v3); -int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_h2c_ba_cam *h2c; - u8 macid = rtwsta_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; + u8 macid; int ret; + rtwsta_link = rtw89_get_designated_link(rtwsta); + rtwvif_link = rtwsta_link->rtwvif_link; + + macid = rtwsta_link->mac_id; + ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because @@ -2741,24 +2746,33 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev) } } -int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_h2c_ba_cam_v1 *h2c; - u8 macid = rtwsta_link->mac_id; + struct ieee80211_vif *vif; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; u8 bmap_size; + bool is_mld; + u8 macid; int ret; + rtwsta_link = rtw89_get_designated_link(rtwsta); + rtwvif_link = rtwsta_link->rtwvif_link; + vif = rtwvif_link_to_vif(rtwvif_link); + + macid = rtwsta_link->mac_id; + is_mld = ieee80211_vif_is_mld(vif); + ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because @@ -2797,6 +2811,7 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, entry_idx += chip->bacam_dynamic_num; /* std entry right after dynamic ones */ h2c->w1 = le32_encode_bits(entry_idx, RTW89_H2C_BA_CAM_V1_W1_ENTRY_IDX_MASK) | le32_encode_bits(1, RTW89_H2C_BA_CAM_V1_W1_STD_ENTRY_EN) | + le32_encode_bits(is_mld, RTW89_H2C_BA_CAM_V1_W1_MLD_EN) | le32_encode_bits(!!rtwvif_link->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); @@ -2820,24 +2835,33 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_ba_cam_v1); -int rtw89_fw_h2c_ba_cam_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam_g7(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_h2c_ba_cam_g7 *h2c; - u16 macid = rtwsta_link->mac_id; + struct ieee80211_vif *vif; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; u8 bmap_size; + bool is_mld; + u16 macid; int ret; + rtwsta_link = rtw89_get_designated_link(rtwsta); + rtwvif_link = rtwsta_link->rtwvif_link; + vif = rtwvif_link_to_vif(rtwvif_link); + + macid = rtwsta_link->mac_id; + is_mld = ieee80211_vif_is_mld(vif); + ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); if (ret) { /* @@ -2871,6 +2895,7 @@ int rtw89_fw_h2c_ba_cam_g7(struct rtw89_dev *rtwdev, le32_encode_bits(1, RTW89_H2C_BA_CAM_G7_W0_INIT_REQ) | le32_encode_bits(params->tid, RTW89_H2C_BA_CAM_G7_W0_TID_MASK) | le32_encode_bits(1, RTW89_H2C_BA_CAM_G7_W0_STD_ENTRY_EN) | + le32_encode_bits(is_mld, RTW89_H2C_BA_CAM_G7_W0_MLD_EN) | le32_encode_bits(!!rtwvif_link->mac_idx, RTW89_H2C_BA_CAM_G7_W0_BAND_SEL) | le32_encode_bits(bmap_size, RTW89_H2C_BA_CAM_G7_W0_BMAP_SIZE_MASK) | diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index a15a5967cabc..9ab21d6afcf3 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -5593,17 +5593,11 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, 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_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params); -int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params); -int rtw89_fw_h2c_ba_cam_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, +int rtw89_fw_h2c_ba_cam_g7(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params); void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, @@ -5845,20 +5839,8 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_vif_link *rtwvif_link; - struct rtw89_sta_link *rtwsta_link; - unsigned int link_id; - int ret; - - rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { - rtwvif_link = rtwsta_link->rtwvif_link; - ret = chip->ops->h2c_ba_cam(rtwdev, rtwvif_link, rtwsta_link, - valid, params); - if (ret) - return ret; - } - return 0; + return chip->ops->h2c_ba_cam(rtwdev, rtwsta, valid, params); } static inline diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index cf356a54d91c..9e6cafc492c4 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -519,6 +519,8 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&rtwsta->dlink_pool); skb_queue_head_init(&rtwsta->roc_queue); + + INIT_LIST_HEAD(&rtwsta->ba_cam_list); bitmap_zero(rtwsta->pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM); rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id); diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index a507ce1fcd63..701440bd7be1 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -327,6 +327,8 @@ static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) if (rtwvif != target_rtwvif) return; + INIT_LIST_HEAD(&rtwsta->ba_cam_list); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { rtwvif_link = rtwsta_link->rtwvif_link; @@ -334,8 +336,6 @@ static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); if (sta->tdls) rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); - - INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); } } base-commit: 73e3b1c94c7d5b4a113e7cbb42665dc2fe3b9d78 -- 2.25.1