diff options
author | Kalle Valo <kvalo@kernel.org> | 2024-10-17 20:21:22 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@kernel.org> | 2024-10-17 20:21:22 +0300 |
commit | 1f3de77752a7bf0d1beb44603f048eb46948b9fe (patch) | |
tree | d071a3fa516d2da2b2b38cc9e522d66a607a29ae | |
parent | b2d23b83d8d017fa031fe9d2552d8007bfdb88b8 (diff) | |
parent | fc442560016d9246460b317771bebbcbaf910aa2 (diff) |
Merge tag 'rtw-next-2024-10-10' of https://github.com/pkshih/rtw
rtw-next patches for v6.13
No big change at this point. Regular development and fixes are listed:
rtl8xxxu:
- correct beaconing for the case of STA + AP
rtw88:
- consolidate parser of RX descriptor as preparation to support coming
chips
rtw89:
- update BT-coexistence to improve user experience for RTL8852BE and
RTL8852BE-VT
- correct RTL8922AE RF calibration timeout time and print out firmware
log
- set proper PCI EQ value for RTL8852CE and RTL8922AE
- adjust to support MLO continuously
50 files changed, 4443 insertions, 2406 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c index 7891c988dd5f..f95898f68d68 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -5058,10 +5058,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (bss_conf->enable_beacon) + if (bss_conf->enable_beacon) { rtl8xxxu_start_tx_beacon(priv); - else + schedule_delayed_work(&priv->update_beacon_work, 0); + } else { rtl8xxxu_stop_tx_beacon(priv); + } } if (changed & BSS_CHANGED_BEACON) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 0e77de1baaf8..bcfc53af4c1a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -2040,31 +2040,33 @@ static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int params[] = {RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID, - EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, - EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, - COUNTRY_CODE_WORLD_WIDE_13}; + static const int params[] = { + RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID, + EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, + EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, + COUNTRY_CODE_WORLD_WIDE_13 + }; u8 *hwinfo; int i; bool is_toshiba_smid1 = false; bool is_toshiba_smid2 = false; bool is_samsung_smid = false; bool is_lenovo_smid = false; - u16 toshiba_smid1[] = { + static const u16 toshiba_smid1[] = { 0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180, 0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180, 0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185, 0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185 }; - u16 toshiba_smid2[] = { + static const u16 toshiba_smid2[] = { 0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181, 0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185 }; - u16 samsung_smid[] = { + static const u16 samsung_smid[] = { 0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192, 0x8193, 0x9191, 0x9192, 0x9193 }; - u16 lenovo_smid[] = { + static const u16 lenovo_smid[] = { 0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200 }; diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index b9b0114e253b..813c12148819 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -267,7 +267,7 @@ static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload, static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload, u8 length) { - struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload; rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 564f5988ee82..e5abcc20b63c 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -228,7 +228,7 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, } static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, - const struct rtw_pwr_seq_cmd **cmd_seq) + const struct rtw_pwr_seq_cmd * const *cmd_seq) { u8 cut_mask; u8 intf_mask; @@ -271,7 +271,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) { const struct rtw_chip_info *chip = rtwdev->chip; - const struct rtw_pwr_seq_cmd **pwr_seq; + const struct rtw_pwr_seq_cmd * const *pwr_seq; u32 imr = 0; u8 rpwm; bool cur_pwr; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 945117afe143..05cfb235f272 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -848,9 +848,8 @@ struct rtw_chip_ops { void (*phy_set_param)(struct rtw_dev *rtwdev); void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, u8 bandwidth, u8 primary_chan_idx); - void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status); + void (*query_phy_status)(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat); u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, u32 addr, u32 mask); bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, @@ -1167,7 +1166,7 @@ enum rtw_fwcd_item { /* hardware configuration for each IC */ struct rtw_chip_info { - struct rtw_chip_ops *ops; + const struct rtw_chip_ops *ops; u8 id; const char *fw_name; @@ -1209,8 +1208,8 @@ struct rtw_chip_info { /* init values */ u8 sys_func_en; - const struct rtw_pwr_seq_cmd **pwr_on_seq; - const struct rtw_pwr_seq_cmd **pwr_off_seq; + const struct rtw_pwr_seq_cmd * const *pwr_on_seq; + const struct rtw_pwr_seq_cmd * const *pwr_off_seq; const struct rtw_rqpn *rqpn_table; const struct rtw_prioq_addrs *prioq_addrs; const struct rtw_page_table *page_table; @@ -1242,7 +1241,7 @@ struct rtw_chip_info { u8 bfer_su_max_num; u8 bfer_mu_max_num; - struct rtw_hw_reg_offset *edcca_th; + const struct rtw_hw_reg_offset *edcca_th; s8 l2h_th_ini_cs; s8 l2h_th_ini_ad; diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 0b9b8807af2c..f71e41d6f97c 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1065,7 +1065,7 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE, DMA_FROM_DEVICE); rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); /* offset from rx_desc to payload */ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 37ef80c9091d..d57a2aabd89b 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -123,7 +123,7 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) { - struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; rtw_write32_mask(rtwdev, edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c index 222608de33cd..77399b8dd8cd 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c @@ -29,9 +29,6 @@ #define TBTT_PROHIBIT_HOLD_TIME 0x80 #define TBTT_PROHIBIT_HOLD_TIME_STOP_BCN 0x64 -/* raw pkt_stat->drv_info_sz is in unit of 8-bytes */ -#define RX_DRV_INFO_SZ_UNIT_8703B 8 - #define TRANS_SEQ_END \ 0xFFFF, \ RTW_PWR_CUT_ALL_MSK, \ @@ -481,14 +478,14 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8703b[] = { {TRANS_SEQ_END}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8703b[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8703b[] = { trans_pre_enable_8703b, trans_carddis_to_cardemu_8703b, trans_cardemu_to_act_8703b, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = { trans_act_to_lps_8703b, trans_act_to_reset_mcu_8703b, trans_act_to_cardemu_8703b, @@ -1032,57 +1029,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, query_phy_status_ofdm(rtwdev, phy_status, pkt_stat); } -static void rtw8703b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = 0; - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - pkt_stat->drv_info_sz *= RX_DRV_INFO_SZ_UNIT_8703B; - - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - - pkt_stat->bw = GET_RX_DESC_BW(rx_desc); - - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); - - /* Rtl8723cs driver checks for size < 14 or size > 8192 and - * simply drops the packet. Maybe this should go into - * rtw_rx_fill_rx_status()? - */ - if (pkt_stat->pkt_len == 0) { - rx_status->flag |= RX_FLAG_NO_PSDU; - rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); - } -} - #define ADDA_ON_VAL_8703B 0x03c00014 static @@ -1941,14 +1887,14 @@ static const struct coex_tdma_para tdma_sant_8703b[] = { { {0x61, 0x08, 0x03, 0x11, 0x11} }, }; -static struct rtw_chip_ops rtw8703b_ops = { +static const struct rtw_chip_ops rtw8703b_ops = { .mac_init = rtw8723x_mac_init, .dump_fw_crash = NULL, .shutdown = NULL, .read_efuse = rtw8703b_read_efuse, .phy_set_param = rtw8703b_phy_set_param, .set_channel = rtw8703b_set_channel, - .query_rx_desc = rtw8703b_query_rx_desc, + .query_phy_status = query_phy_status, .read_rf = rtw_phy_read_rf_sipi, .write_rf = rtw_phy_write_rf_reg_sipi, .set_tx_power_index = rtw8723x_set_tx_power_index, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 3fba4054d45f..86a5e2497641 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -227,47 +227,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = 0; - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev, u8 channel, u32 thres) { @@ -1430,10 +1389,10 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) dm_info->pwr_trk_triggered = false; } -static struct rtw_chip_ops rtw8723d_ops = { +static const struct rtw_chip_ops rtw8723d_ops = { .phy_set_param = rtw8723d_phy_set_param, .read_efuse = rtw8723x_read_efuse, - .query_rx_desc = rtw8723d_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8723d_set_channel, .mac_init = rtw8723x_mac_init, .shutdown = rtw8723d_shutdown, @@ -1788,7 +1747,7 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8723d[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8723d[] = { trans_carddis_to_cardemu_8723d, trans_cardemu_to_act_8723d, NULL @@ -2004,7 +1963,7 @@ static const struct rtw_pwr_seq_cmd trans_act_to_post_carddis_8723d[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8723d[] = { trans_act_to_lps_8723d, trans_act_to_pre_carddis_8723d, trans_act_to_cardemu_8723d, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index 526e8de77b3e..66c79956e8e5 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -679,47 +679,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) { @@ -1254,7 +1213,7 @@ static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, fill_txdesc_checksum_common(txdesc, 16); } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1292,7 +1251,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { {0x0020, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -1396,7 +1355,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { {0x0093, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1454,7 +1413,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { {0x0007, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -1567,13 +1526,13 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8821c[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8821c[] = { trans_carddis_to_cardemu_8821c, trans_cardemu_to_act_8821c, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8821c[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8821c[] = { trans_act_to_cardemu_8821c, trans_cardemu_to_carddis_8821c, NULL @@ -1629,7 +1588,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { [6] = RTW_DEF_RFE(8821c, 0, 0), }; -static struct rtw_hw_reg rtw8821c_dig[] = { +static const struct rtw_hw_reg rtw8821c_dig[] = { [0] = { .addr = 0xc50, .mask = 0x7f }, }; @@ -1639,7 +1598,7 @@ static const struct rtw_ltecoex_addr rtw8821c_ltecoex_addr = { .rdata = LTECOEX_READ_DATA, }; -static struct rtw_page_table page_table_8821c[] = { +static const struct rtw_page_table page_table_8821c[] = { /* not sure what [0] stands for */ {16, 16, 16, 14, 1}, {16, 16, 16, 14, 1}, @@ -1648,7 +1607,7 @@ static struct rtw_page_table page_table_8821c[] = { {16, 16, 16, 14, 1}, }; -static struct rtw_rqpn rqpn_table_8821c[] = { +static const struct rtw_rqpn rqpn_table_8821c[] = { /* not sure what [0] stands for */ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, @@ -1667,7 +1626,7 @@ static struct rtw_rqpn rqpn_table_8821c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8821c = { +static const struct rtw_prioq_addrs prioq_addrs_8821c = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -1683,10 +1642,10 @@ static struct rtw_prioq_addrs prioq_addrs_8821c = { .wsize = true, }; -static struct rtw_chip_ops rtw8821c_ops = { +static const struct rtw_chip_ops rtw8821c_ops = { .phy_set_param = rtw8821c_phy_set_param, .read_efuse = rtw8821c_read_efuse, - .query_rx_desc = rtw8821c_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8821c_set_channel, .mac_init = rtw8821c_mac_init, .read_rf = rtw_phy_read_rf, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 6edb17aea90e..24f76a36f23e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -934,47 +934,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) { @@ -1978,13 +1937,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822b[] = { trans_carddis_to_cardemu_8822b, trans_cardemu_to_act_8822b, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822b[] = { trans_act_to_cardemu_8822b, trans_cardemu_to_carddis_8822b, NULL @@ -2156,7 +2115,7 @@ static const struct rtw_rqpn rqpn_table_8822b[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8822b = { +static const struct rtw_prioq_addrs prioq_addrs_8822b = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -2172,10 +2131,10 @@ static struct rtw_prioq_addrs prioq_addrs_8822b = { .wsize = true, }; -static struct rtw_chip_ops rtw8822b_ops = { +static const struct rtw_chip_ops rtw8822b_ops = { .phy_set_param = rtw8822b_phy_set_param, .read_efuse = rtw8822b_read_efuse, - .query_rx_desc = rtw8822b_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8822b_set_channel, .mac_init = rtw8822b_mac_init, .read_rf = rtw_phy_read_rf, @@ -2521,7 +2480,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, }; -static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { +static const struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0}, [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0}, }; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 1dbe1cdbc3fd..da74e66bda84 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -2690,48 +2690,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - pkt_stat->hdr = hdr; - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck, u8 *tx_pwr_ref_ofdm) @@ -4874,13 +4832,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822c[] = { trans_carddis_to_cardemu_8822c, trans_cardemu_to_act_8822c, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822c[] = { trans_act_to_cardemu_8822c, trans_cardemu_to_carddis_8822c, NULL @@ -4972,7 +4930,7 @@ static const struct rtw_rqpn rqpn_table_8822c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8822c = { +static const struct rtw_prioq_addrs prioq_addrs_8822c = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -4988,10 +4946,10 @@ static struct rtw_prioq_addrs prioq_addrs_8822c = { .wsize = true, }; -static struct rtw_chip_ops rtw8822c_ops = { +static const struct rtw_chip_ops rtw8822c_ops = { .phy_set_param = rtw8822c_phy_set_param, .read_efuse = rtw8822c_read_efuse, - .query_rx_desc = rtw8822c_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8822c_set_channel, .mac_init = rtw8822c_mac_init, .dump_fw_crash = rtw8822c_dump_fw_crash, @@ -5301,7 +5259,7 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, }; -static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { +static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { [EDCCA_TH_L2H_IDX] = { {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80 }, diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c index 66f9419588cf..1de93fc9efe9 100644 --- a/drivers/net/wireless/realtek/rtw88/rx.c +++ b/drivers/net/wireless/realtek/rtw88/rx.c @@ -187,11 +187,10 @@ fill_rx_status: } EXPORT_SYMBOL(rtw_update_rx_freq_from_ie); -void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_hdr *hdr, - struct ieee80211_rx_status *rx_status, - u8 *phy_status) +static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) { struct ieee80211_hw *hw = rtwdev->hw; u8 path; @@ -242,5 +241,64 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, } rtw_rx_addr_match(rtwdev, pkt_stat, hdr); + + /* Rtl8723cs driver checks for size < 14 or size > 8192 and + * simply drops the packet. + */ + if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) { + rx_status->flag |= RX_FLAG_NO_PSDU; + rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); + } +} + +void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status) +{ + u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; + struct rtw_rx_desc *rx_desc = rx_desc8; + struct ieee80211_hdr *hdr; + u32 enc_type, swdec; + void *phy_status; + + memset(pkt_stat, 0, sizeof(*pkt_stat)); + + pkt_stat->pkt_len = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PKT_LEN); + pkt_stat->crc_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_CRC32); + pkt_stat->icv_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ICV_ERR); + pkt_stat->drv_info_sz = le32_get_bits(rx_desc->w0, + RTW_RX_DESC_W0_DRV_INFO_SIZE); + enc_type = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ENC_TYPE); + pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT); + pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST); + swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC); + pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE; + + pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID); + + pkt_stat->is_c2h = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_C2H); + pkt_stat->ppdu_cnt = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_PPDU_CNT); + + pkt_stat->rate = le32_get_bits(rx_desc->w3, RTW_RX_DESC_W3_RX_RATE); + + pkt_stat->bw = le32_get_bits(rx_desc->w4, RTW_RX_DESC_W4_BW); + + pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL); + + /* drv_info_sz is in unit of 8-bytes */ + pkt_stat->drv_info_sz *= 8; + + /* c2h cmd pkt's rx/phy status is not interested */ + if (pkt_stat->is_c2h) + return; + + phy_status = rx_desc8 + desc_sz + pkt_stat->shift; + hdr = phy_status + pkt_stat->drv_info_sz; + pkt_stat->hdr = hdr; + + if (pkt_stat->phy_status) + rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat); + + rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status); } -EXPORT_SYMBOL(rtw_rx_fill_rx_status); +EXPORT_SYMBOL(rtw_rx_query_rx_desc); diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h index 9f0019112987..6b7dee245c0a 100644 --- a/drivers/net/wireless/realtek/rtw88/rx.h +++ b/drivers/net/wireless/realtek/rtw88/rx.h @@ -14,42 +14,40 @@ enum rtw_rx_desc_enc { RX_DESC_ENC_WEP104 = 5, }; -#define GET_RX_DESC_PHYST(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26)) -#define GET_RX_DESC_ICV_ERR(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15)) -#define GET_RX_DESC_CRC32(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14)) -#define GET_RX_DESC_SWDEC(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27)) -#define GET_RX_DESC_C2H(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28)) -#define GET_RX_DESC_PKT_LEN(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0)) -#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16)) -#define GET_RX_DESC_SHIFT(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24)) -#define GET_RX_DESC_ENC_TYPE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20)) -#define GET_RX_DESC_RX_RATE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0)) -#define GET_RX_DESC_MACID(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0)) -#define GET_RX_DESC_PPDU_CNT(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29)) -#define GET_RX_DESC_TSFL(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0)) -#define GET_RX_DESC_BW(rxdesc) \ - (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4))) +struct rtw_rx_desc { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; +} __packed; + +#define RTW_RX_DESC_W0_PKT_LEN GENMASK(13, 0) +#define RTW_RX_DESC_W0_CRC32 BIT(14) +#define RTW_RX_DESC_W0_ICV_ERR BIT(15) +#define RTW_RX_DESC_W0_DRV_INFO_SIZE GENMASK(19, 16) +#define RTW_RX_DESC_W0_ENC_TYPE GENMASK(22, 20) +#define RTW_RX_DESC_W0_SHIFT GENMASK(25, 24) +#define RTW_RX_DESC_W0_PHYST BIT(26) +#define RTW_RX_DESC_W0_SWDEC BIT(27) + +#define RTW_RX_DESC_W1_MACID GENMASK(6, 0) + +#define RTW_RX_DESC_W2_C2H BIT(28) +#define RTW_RX_DESC_W2_PPDU_CNT GENMASK(30, 29) + +#define RTW_RX_DESC_W3_RX_RATE GENMASK(6, 0) + +#define RTW_RX_DESC_W4_BW GENMASK(5, 4) + +#define RTW_RX_DESC_W5_TSFL GENMASK(31, 0) void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, struct sk_buff *skb); -void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_hdr *hdr, - struct ieee80211_rx_status *rx_status, - u8 *phy_status); +void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status); void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status, struct rtw_rx_pkt_stat *pkt_stat); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 21d0754dd7f6..f0b06ed8f76d 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -981,8 +981,7 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) while (true) { rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, - &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + pkt_stat.shift; @@ -1297,12 +1296,12 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev) struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; int i; - for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) - skb_queue_purge(&rtwsdio->tx_queue[i]); - flush_workqueue(rtwsdio->txwq); destroy_workqueue(rtwsdio->txwq); kfree(rtwsdio->tx_handler_data); + + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) + ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]); } int rtw_sdio_probe(struct sdio_func *sdio_func, diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index e83ab6fb83f5..ba314d90ab3f 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -423,10 +423,11 @@ static void rtw_usb_tx_handler(struct work_struct *work) static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb) { + struct rtw_dev *rtwdev = rtwusb->rtwdev; int i; for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) - skb_queue_purge(&rtwusb->tx_queue[i]); + ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]); } static void rtw_usb_write_port_complete(struct urb *urb) @@ -570,8 +571,8 @@ static void rtw_usb_rx_handler(struct work_struct *work) do { rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, - &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, + &rx_status); pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + pkt_stat.shift; @@ -889,9 +890,9 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) { struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); - rtw_usb_tx_queue_purge(rtwusb); flush_workqueue(rtwusb->txwq); destroy_workqueue(rtwusb->txwq); + rtw_usb_tx_queue_purge(rtwusb); } static int rtw_usb_intf_init(struct rtw_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 4476fc7e53db..8d140b94cb44 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -211,25 +211,17 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam, return 0; } -static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - const struct rtw89_sec_cam_entry *sec_cam, - bool inform_fw) +static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + const struct rtw89_sec_cam_entry *sec_cam, + bool inform_fw) { - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif; struct rtw89_addr_cam_entry *addr_cam; unsigned int i; int ret = 0; - if (!vif) { - rtw89_err(rtwdev, "No iface for deleting sec cam\n"); - return -EINVAL; - } - - rtwvif = (struct rtw89_vif *)vif->drv_priv; - addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx) @@ -239,11 +231,11 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, } if (inform_fw) { - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); } @@ -251,25 +243,17 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, return ret; } -static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key, - struct rtw89_sec_cam_entry *sec_cam) +static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_key_conf *key, + struct rtw89_sec_cam_entry *sec_cam) { - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif; struct rtw89_addr_cam_entry *addr_cam; u8 key_idx = 0; int ret; - if (!vif) { - rtw89_err(rtwdev, "No iface for adding sec cam\n"); - return -EINVAL; - } - - rtwvif = (struct rtw89_vif *)vif->drv_priv; - addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) @@ -285,13 +269,13 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, addr_cam->sec_ent_keyid[key_idx] = key->keyidx; addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx; set_bit(key_idx, addr_cam->sec_cam_map); - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", ret); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", ret); @@ -302,6 +286,92 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, return 0; } +static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + const struct rtw89_sec_cam_entry *sec_cam, + bool inform_fw) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *rtwvif; + unsigned int link_id; + int ret; + + if (!vif) { + rtw89_err(rtwdev, "No iface for deleting sec cam\n"); + return -EINVAL; + } + + rtwvif = vif_to_rtwvif(vif); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL; + if (rtwsta && !rtwsta_link) + continue; + + ret = __rtw89_cam_detach_sec_cam(rtwdev, rtwvif_link, rtwsta_link, + sec_cam, inform_fw); + if (ret) + return ret; + } + + return 0; +} + +static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + struct rtw89_sec_cam_entry *sec_cam) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *rtwvif; + unsigned int link_id; + int key_link_id; + int ret; + + if (!vif) { + rtw89_err(rtwdev, "No iface for adding sec cam\n"); + return -EINVAL; + } + + rtwvif = vif_to_rtwvif(vif); + + key_link_id = ieee80211_vif_is_mld(vif) ? key->link_id : 0; + if (key_link_id >= 0) { + rtwvif_link = rtwvif->links[key_link_id]; + rtwsta_link = rtwsta ? rtwsta->links[key_link_id] : NULL; + + if (!rtwvif_link || (rtwsta && !rtwsta_link)) { + rtw89_err(rtwdev, "No drv link for adding sec cam\n"); + return -ENOLINK; + } + + return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, + rtwsta_link, key, sec_cam); + } + + /* key_link_id < 0: MLD pairwise key */ + if (!rtwsta) { + rtw89_err(rtwdev, "No sta for adding MLD pairwise sec cam\n"); + return -EINVAL; + } + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, + rtwsta_link, key, sec_cam); + if (ret) + return ret; + } + + return 0; +} + static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -485,10 +555,10 @@ void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map); } -void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; rtw89_cam_deinit_addr_cam(rtwdev, addr_cam); rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam); @@ -593,7 +663,7 @@ static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev, } int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_bssid_cam_entry *bssid_cam, const u8 *bssid) { @@ -613,7 +683,7 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, } bssid_cam->bssid_cam_idx = bssid_cam_idx; - bssid_cam->phy_idx = rtwvif->phy_idx; + bssid_cam->phy_idx = rtwvif_link->phy_idx; bssid_cam->len = BSSID_CAM_ENT_SIZE; bssid_cam->offset = 0; bssid_cam->valid = true; @@ -622,20 +692,21 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, return 0; } -void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; - ether_addr_copy(bssid_cam->bssid, rtwvif->bssid); + ether_addr_copy(bssid_cam->bssid, rtwvif_link->bssid); } -int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; int ret; - ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid); + ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, + rtwvif_link->bssid); if (ret) { rtw89_err(rtwdev, "failed to init bssid cam\n"); return ret; @@ -651,19 +722,27 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) } int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, u8 *cmd) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, u8 *cmd) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); - u8 bss_color = vif->bss_conf.he_bss_color.color; + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); + struct ieee80211_bss_conf *bss_conf; + u8 bss_color; u8 bss_mask; - if (vif->bss_conf.nontransmitted) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + bss_color = bss_conf->he_bss_color.color; + + if (bss_conf->nontransmitted) bss_mask = RTW89_BSSID_MATCH_5_BYTES; else bss_mask = RTW89_BSSID_MATCH_ALL; + rcu_read_unlock(); + FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); @@ -694,19 +773,30 @@ static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr) } void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, u8 *cmd) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); - struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); - const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); + struct ieee80211_link_sta *link_sta; + const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; u8 sma_hash, tma_hash, addr_msk_start; u8 sma_start = 0; u8 tma_start = 0; - u8 *tma = sta ? sta->addr : rtwvif->bssid; + const u8 *tma; + + rcu_read_lock(); + + if (sta) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + tma = link_sta->addr; + } else { + tma = rtwvif_link->bssid; + } if (addr_cam->addr_mask != 0) { addr_msk_start = __ffs(addr_cam->addr_mask); @@ -723,10 +813,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); - FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type); - FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond); - FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule); - FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx); + FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type); + FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond); + FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule); + FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx); FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); @@ -748,20 +838,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_TMA4(cmd, tma[4]); FWCMD_SET_ADDR_TMA5(cmd, tma[5]); - FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port); - FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port); - FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger); - FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop); - FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind); - FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind); - FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id); - if (rtwvif->net_type == RTW89_NET_TYPE_INFRA) + FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port); + FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port); + FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger); + FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); + FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); + FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); + FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id); + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); - else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); - FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern); - FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc); - FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic); + FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern); + FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc); + FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic); FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); @@ -780,18 +871,22 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); + + rcu_read_unlock(); } void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v1 *h2c) { - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; - h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, + h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id, DCTLINFO_V1_C0_MACID) | le32_encode_bits(1, DCTLINFO_V1_C0_OP); @@ -862,15 +957,17 @@ void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, } void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v2 *h2c) { - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; - h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, + h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id, DCTLINFO_V2_C0_MACID) | le32_encode_bits(1, DCTLINFO_V2_C0_OP); diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index 5d7b624c2dd4..a6f72edd30fe 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -526,34 +526,34 @@ struct rtw89_h2c_dctlinfo_ud_v2 { #define DCTLINFO_V2_W12_MLD_TA_BSSID_H_V1 GENMASK(15, 0) #define DCTLINFO_V2_W12_ALL GENMASK(15, 0) -int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); -void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev, struct rtw89_addr_cam_entry *addr_cam, const struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev, struct rtw89_addr_cam_entry *addr_cam); int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_bssid_cam_entry *bssid_cam, const u8 *bssid); void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *vif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *vif, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, u8 *cmd); void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v1 *h2c); void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v2 *h2c); int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, u8 *cmd); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, u8 *cmd); int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -564,6 +564,6 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, struct ieee80211_key_conf *key, bool inform_fw); void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 7070c85e2c28..ba6332da8019 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -234,6 +234,18 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) rtw89_config_default_chandef(rtwdev); } +static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->chanctx_assigned) + return true; + + return false; +} + static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, struct rtw89_entity_weight *w) { @@ -255,7 +267,7 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, } rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (rtwvif->chanctx_assigned) + if (rtw89_vif_is_active_role(rtwvif)) w->active_roles++; } } @@ -387,9 +399,9 @@ int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev, static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, u64 tsf) { - struct rtw89_vif *rtwvif = role->rtwvif; + struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval); - u64 sync_tsf = READ_ONCE(rtwvif->sync_bcn_tsf); + u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); u32 remainder; if (tsf < sync_tsf) { @@ -413,8 +425,8 @@ static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux int ret; req.group = mcc->group; - req.macid_x = ref->rtwvif->mac_id; - req.macid_y = aux->rtwvif->mac_id; + req.macid_x = ref->rtwvif_link->mac_id; + req.macid_y = aux->rtwvif_link->mac_id; ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -440,10 +452,10 @@ static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES); arg.num = 2; - arg.infos[0].band = ref->rtwvif->mac_idx; - arg.infos[0].port = ref->rtwvif->port; - arg.infos[1].band = aux->rtwvif->mac_idx; - arg.infos[1].port = aux->rtwvif->port; + arg.infos[0].band = ref->rtwvif_link->mac_idx; + arg.infos[0].port = ref->rtwvif_link->port; + arg.infos[1].band = aux->rtwvif_link->mac_idx; + arg.infos[1].port = aux->rtwvif_link->port; ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt); if (ret) { @@ -522,23 +534,31 @@ out: static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_mcc_role *mcc_role = data; - struct rtw89_vif *target = mcc_role->rtwvif; + struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; if (rtwvif != target) return; - rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta->mac_id); + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n"); + return; + } + + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id); } static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *mcc_role) { - struct rtw89_vif *rtwvif = mcc_role->rtwvif; + struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; - rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif->mac_id); + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id); ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_mcc_role_macid_sta_iter, mcc_role); @@ -564,8 +584,9 @@ static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev, static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *mcc_role) { - struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif); + struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; struct ieee80211_p2p_noa_desc *noa_desc; + struct ieee80211_bss_conf *bss_conf; u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval); u32 max_toa_us, max_tob_us, max_dur_us; u32 start_time, interval, duration; @@ -576,13 +597,18 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, if (!mcc_role->is_go && !mcc_role->is_gc) return; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + /* find the first periodic NoA */ for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { - noa_desc = &vif->bss_conf.p2p_noa_attr.desc[i]; + noa_desc = &bss_conf->p2p_noa_attr.desc[i]; if (noa_desc->count == 255) goto fill; } + rcu_read_unlock(); return; fill: @@ -590,6 +616,8 @@ fill: interval = le32_to_cpu(noa_desc->interval); duration = le32_to_cpu(noa_desc->duration); + rcu_read_unlock(); + if (interval != bcn_intvl_us) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC role limit: mismatch interval: %d vs. %d\n", @@ -597,7 +625,7 @@ fill: return; } - ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return; @@ -632,15 +660,21 @@ fill: } static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_mcc_role *role) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; const struct rtw89_chan *chan; memset(role, 0, sizeof(*role)); - role->rtwvif = rtwvif; - role->beacon_interval = vif->bss_conf.beacon_int; + role->rtwvif_link = rtwvif_link; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + role->beacon_interval = bss_conf->beacon_int; + + rcu_read_unlock(); if (!role->beacon_interval) { rtw89_warn(rtwdev, @@ -650,10 +684,10 @@ static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, role->duration = role->beacon_interval / 2; - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); role->is_2ghz = chan->band_type == RTW89_BAND_2G; - role->is_go = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_GO; - role->is_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO; + role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; rtw89_mcc_fill_role_macid_bitmap(rtwdev, role); rtw89_mcc_fill_role_policy(rtwdev, role); @@ -678,7 +712,7 @@ static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev) } struct rtw89_mcc_fill_role_selector { - struct rtw89_vif *bind_vif[NUM_OF_RTW89_CHANCTX]; + struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX]; }; static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES); @@ -689,7 +723,7 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, void *data) { struct rtw89_mcc_fill_role_selector *sel = data; - struct rtw89_vif *role_vif = sel->bind_vif[ordered_idx]; + struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx]; int ret; if (!role_vif) { @@ -712,21 +746,28 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) { struct rtw89_mcc_fill_role_selector sel = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; int ret; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (!rtwvif->chanctx_assigned) + if (!rtw89_vif_is_active_role(rtwvif)) + continue; + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n"); continue; + } - if (sel.bind_vif[rtwvif->chanctx_idx]) { + if (sel.bind_vif[rtwvif_link->chanctx_idx]) { rtw89_warn(rtwdev, "MCC skip extra vif <macid %d> on chanctx[%d]\n", - rtwvif->mac_id, rtwvif->chanctx_idx); + rtwvif_link->mac_id, rtwvif_link->chanctx_idx); continue; } - sel.bind_vif[rtwvif->chanctx_idx] = rtwvif; + sel.bind_vif[rtwvif_link->chanctx_idx] = rtwvif_link; } ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel); @@ -754,13 +795,13 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, memset(&pattern->courtesy, 0, sizeof(pattern->courtesy)); if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) { - pattern->courtesy.macid_tgt = aux->rtwvif->mac_id; - pattern->courtesy.macid_src = ref->rtwvif->mac_id; + pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id; + pattern->courtesy.macid_src = ref->rtwvif_link->mac_id; pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; pattern->courtesy.enable = true; } else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) { - pattern->courtesy.macid_tgt = ref->rtwvif->mac_id; - pattern->courtesy.macid_src = aux->rtwvif->mac_id; + pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id; + pattern->courtesy.macid_src = aux->rtwvif_link->mac_id; pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; pattern->courtesy.enable = true; } @@ -1263,7 +1304,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, u64 tsf_src; int ret; - ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif, &tsf_src); + ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return; @@ -1280,12 +1321,12 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder); tsf_ofst_tgt = bcn_intvl_src_us - remainder; - config->sync.macid_tgt = tgt->rtwvif->mac_id; - config->sync.band_tgt = tgt->rtwvif->mac_idx; - config->sync.port_tgt = tgt->rtwvif->port; - config->sync.macid_src = src->rtwvif->mac_id; - config->sync.band_src = src->rtwvif->mac_idx; - config->sync.port_src = src->rtwvif->port; + config->sync.macid_tgt = tgt->rtwvif_link->mac_id; + config->sync.band_tgt = tgt->rtwvif_link->mac_idx; + config->sync.port_tgt = tgt->rtwvif_link->port; + config->sync.macid_src = src->rtwvif_link->mac_id; + config->sync.band_src = src->rtwvif_link->mac_idx; + config->sync.port_src = src->rtwvif_link->port; config->sync.offset = tsf_ofst_tgt / 1024; config->sync.enable = true; @@ -1294,7 +1335,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, config->sync.macid_tgt, config->sync.macid_src, config->sync.offset); - rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif, src->rtwvif, + rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link, config->sync.offset); } @@ -1305,13 +1346,13 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) struct rtw89_mcc_config *config = &mcc->config; u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval); u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref); - struct rtw89_vif *rtwvif = ref->rtwvif; + struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link; u64 tsf, start_tsf; u32 cur_tbtt_ofst; u64 min_time; int ret; - ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return ret; @@ -1390,13 +1431,13 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro const struct rtw89_chan *chan; int ret; - chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); req.central_ch_seg0 = chan->channel; req.primary_ch = chan->primary_channel; req.bandwidth = chan->band_width; req.ch_band_type = chan->band_type; - req.macid = role->rtwvif->mac_id; + req.macid = role->rtwvif_link->mac_id; req.group = mcc->group; req.c2h_rpt = policy->c2h_rpt; req.tx_null_early = policy->tx_null_early; @@ -1421,7 +1462,7 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro } ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, - role->rtwvif->mac_id, + role->rtwvif_link->mac_id, role->macid_bitmap); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -1448,7 +1489,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, slot_arg->duration = role->duration; slot_arg->role_num = 1; - chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI; slot_arg->roles[0].is_master = role == ref; @@ -1458,7 +1499,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, slot_arg->roles[0].primary_ch = chan->primary_channel; slot_arg->roles[0].en_tx_null = !policy->dis_tx_null; slot_arg->roles[0].null_early = policy->tx_null_early; - slot_arg->roles[0].macid = role->rtwvif->mac_id; + slot_arg->roles[0].macid = role->rtwvif_link->mac_id; slot_arg->roles[0].macid_main_bitmap = rtw89_mcc_role_fw_macid_bitmap_to_u32(role); } @@ -1569,7 +1610,7 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace) } } - req.macid = ref->rtwvif->mac_id; + req.macid = ref->rtwvif_link->mac_id; req.tsf_high = config->start_tsf >> 32; req.tsf_low = config->start_tsf; @@ -1598,7 +1639,7 @@ static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev, if (!courtesy->enable) return; - if (courtesy->macid_src == ref->rtwvif->mac_id) { + if (courtesy->macid_src == ref->rtwvif_link->mac_id) { slot_arg_src = &arg->slots[ref->slot_idx]; slot_idx_tgt = aux->slot_idx; } else { @@ -1717,9 +1758,9 @@ static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_chang struct rtw89_fw_mcc_duration req = { .group = mcc->group, .btc_in_group = false, - .start_macid = ref->rtwvif->mac_id, - .macid_x = ref->rtwvif->mac_id, - .macid_y = aux->rtwvif->mac_id, + .start_macid = ref->rtwvif_link->mac_id, + .macid_x = ref->rtwvif_link->mac_id, + .macid_y = aux->rtwvif_link->mac_id, .duration_x = ref->duration, .duration_y = aux->duration, .start_tsf_high = config->start_tsf >> 32, @@ -1813,18 +1854,18 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable) struct ieee80211_p2p_noa_desc noa_desc = {}; u64 start_time = config->start_tsf; u32 interval = config->mcc_interval; - struct rtw89_vif *rtwvif_go; + struct rtw89_vif_link *rtwvif_go; u32 duration; if (mcc->mode != RTW89_MCC_MODE_GO_STA) return; if (ref->is_go) { - rtwvif_go = ref->rtwvif; + rtwvif_go = ref->rtwvif_link; start_time += ieee80211_tu_to_usec(ref->duration); duration = config->mcc_interval - ref->duration; } else if (aux->is_go) { - rtwvif_go = aux->rtwvif; + rtwvif_go = aux->rtwvif_link; start_time += ieee80211_tu_to_usec(pattern->tob_ref) + ieee80211_tu_to_usec(config->beacon_offset) + ieee80211_tu_to_usec(pattern->toa_aux); @@ -1865,9 +1906,9 @@ static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev) return; if (ref->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true); else if (aux->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true); rtw89_mcc_handle_beacon_noa(rtwdev, true); } @@ -1882,9 +1923,9 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) return; if (ref->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false); else if (aux->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false); rtw89_mcc_handle_beacon_noa(rtwdev, false); } @@ -1942,7 +1983,7 @@ struct rtw89_mcc_stop_sel { static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel, const struct rtw89_mcc_role *mcc_role) { - sel->mac_id = mcc_role->rtwvif->mac_id; + sel->mac_id = mcc_role->rtwvif_link->mac_id; sel->slot_idx = mcc_role->slot_idx; } @@ -1953,7 +1994,7 @@ static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev, { struct rtw89_mcc_stop_sel *sel = data; - if (!mcc_role->rtwvif->chanctx_assigned) + if (!mcc_role->rtwvif_link->chanctx_assigned) return 0; rtw89_mcc_stop_sel_fill(sel, mcc_role); @@ -2081,7 +2122,7 @@ static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, int ret; ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, - upd->rtwvif->mac_id, + upd->rtwvif_link->mac_id, upd->macid_bitmap); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -2106,7 +2147,7 @@ static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, int i; arg.sch_idx = mcc->group; - arg.macid = upd->rtwvif->mac_id; + arg.macid = upd->rtwvif_link->mac_id; for (i = 0; i < 32; i++) { if (add & BIT(i)) { @@ -2144,7 +2185,7 @@ static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev, void *data) { struct rtw89_mcc_role upd = { - .rtwvif = mcc_role->rtwvif, + .rtwvif_link = mcc_role->rtwvif_link, }; int ret; @@ -2370,6 +2411,24 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev) rtw89_queue_chanctx_work(rtwdev); } +static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif, + enum rtw89_chanctx_idx idx1, + enum rtw89_chanctx_idx idx2) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + if (!rtwvif_link->chanctx_assigned) + continue; + + if (rtwvif_link->chanctx_idx == idx1) + rtwvif_link->chanctx_idx = idx2; + else if (rtwvif_link->chanctx_idx == idx2) + rtwvif_link->chanctx_idx = idx1; + } +} + static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx idx1, enum rtw89_chanctx_idx idx2) @@ -2386,14 +2445,8 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, swap(hal->chanctx[idx1], hal->chanctx[idx2]); - rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (!rtwvif->chanctx_assigned) - continue; - if (rtwvif->chanctx_idx == idx1) - rtwvif->chanctx_idx = idx2; - else if (rtwvif->chanctx_idx == idx2) - rtwvif->chanctx_idx = idx1; - } + rtw89_for_each_rtwvif(rtwdev, rtwvif) + __rtw89_swap_chanctx(rtwvif, idx1, idx2); cur = atomic_read(&hal->roc_chanctx_idx); if (cur == idx1) @@ -2444,14 +2497,14 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, } int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx) { struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; struct rtw89_entity_weight w = {}; - rtwvif->chanctx_idx = cfg->idx; - rtwvif->chanctx_assigned = true; + rtwvif_link->chanctx_idx = cfg->idx; + rtwvif_link->chanctx_assigned = true; cfg->ref_count++; if (cfg->idx == RTW89_CHANCTX_0) @@ -2469,7 +2522,7 @@ out: } void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx) { struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; @@ -2479,8 +2532,8 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, enum rtw89_entity_mode new; int ret; - rtwvif->chanctx_idx = RTW89_CHANCTX_0; - rtwvif->chanctx_assigned = false; + rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; + rtwvif_link->chanctx_assigned = false; cfg->ref_count--; if (cfg->ref_count != 0) diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index c6d31984e575..74de13a2e7da 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -43,18 +43,21 @@ struct rtw89_entity_weight { unsigned int active_roles; }; -static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev) +static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { struct rtw89_hal *hal = &rtwdev->hal; - return READ_ONCE(hal->entity_active); + return READ_ONCE(hal->entity_active[phy_idx]); } -static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active) +static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + bool active) { struct rtw89_hal *hal = &rtwdev->hal; - WRITE_ONCE(hal->entity_active, active); + WRITE_ONCE(hal->entity_active[phy_idx], active); } static inline @@ -106,10 +109,10 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx, u32 changed); int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx); #endif diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index df51b29142aa..989e6e882c6e 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -125,6 +125,9 @@ static const u32 cxtbl[] = { 0xfafaaafa, /* 23 */ 0xfafffaff, /* 24 */ 0xea6a5a5a, /* 25 */ + 0xfaff5aff, /* 26 */ + 0xffffdfff, /* 27 */ + 0xe6555555, /* 28 */ }; static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { @@ -134,77 +137,88 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, /* keep it to be the last as default entry */ @@ -213,7 +227,8 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, }; @@ -224,7 +239,7 @@ static const union rtw89_btc_wl_state_map btc_scanning_map = { .scan = 1, .connecting = 1, .roaming = 1, - .transacting = 1, + .dbccing = 1, ._4way = 1, }, }; @@ -3017,7 +3032,7 @@ static void _update_btc_state_map(struct rtw89_dev *rtwdev) struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; if (wl->status.map.connecting || wl->status.map._4way || - wl->status.map.roaming) { + wl->status.map.roaming || wl->status.map.dbccing) { cx->state_map = BTC_WLINKING; } else if (wl->status.map.scan) { /* wl scan */ if (bt_linfo->status.map.inq_pag) @@ -3721,8 +3736,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) tbl_w1 = cxtbl[16]; } - btc->bt_req_en = false; - switch (type) { case BTC_CXP_USERDEF0: btc->update_policy_force = true; @@ -3744,6 +3757,10 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_WL: _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); break; + case BTC_CXP_OFF_WL2: + _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); + _slot_set_type(btc, CXST_OFF, SLOT_ISO); + break; case BTC_CXP_OFF_EQ0: _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); _slot_set_type(btc, CXST_OFF, SLOT_ISO); @@ -3757,6 +3774,12 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_EQ3: _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); break; + case BTC_CXP_OFF_EQ4: + _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); + break; + case BTC_CXP_OFF_EQ5: + _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); + break; case BTC_CXP_OFF_BWB0: _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); break; @@ -3788,7 +3811,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) } break; case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ - btc->bt_req_en = true; _write_scbd(rtwdev, BTC_WSCB_TDMA, true); *t = t_def[CXTD_OFF_EXT]; @@ -3831,9 +3853,9 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); break; case BTC_CXP_OFFE_2GBWMIXB: - _slot_set(btc, CXST_E2G, 0, 0x55555555, SLOT_MIX); + _slot_set(btc, CXST_E2G, 0, 0xea5a5555, SLOT_MIX); _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - cpu_to_le32(0x55555555), s_def[CXST_EBT].cxtype); + s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); break; case BTC_CXP_OFFE_WL: /* for 4-way */ _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX); @@ -3842,6 +3864,8 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) default: break; } + _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, + s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); break; @@ -4246,6 +4270,7 @@ static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec, _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); break; case BTC_ANT_WRFK: + case BTC_ANT_WRFK2: rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); @@ -4623,12 +4648,21 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) static void _action_bt_pan(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; + struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; + struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); switch (btc->cx.state_map) { case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ - _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + if (a2dp.active || !pan.exist) { + btc->dm.slot_dur[CXST_W1] = 80; + btc->dm.slot_dur[CXST_B1] = 20; + _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); + } else { + _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + } break; case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); @@ -4814,8 +4848,16 @@ static void _action_wl_rfk(struct rtw89_dev *rtwdev) rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", __func__, rfk.band); - _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); - _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + btc->dm.tdma_instant_excute = 1; + + if (rfk.state == BTC_WRFK_ONESHOT_START || + btc->ant_type == BTC_ANT_SHARED) { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); + _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); + } else { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); + _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + } } static void _set_btg_ctrl(struct rtw89_dev *rtwdev) @@ -4855,6 +4897,8 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev) if (rtwdev->dbcc_en) { if (ver->fwlrole == 0) { + wl_rinfo.dbcc_2g_phy = RTW89_PHY_MAX; + for (i = 0; i < RTW89_PHY_MAX; i++) { if (wl_dinfo->real_band[i] == RTW89_BAND_2G) wl_rinfo.dbcc_2g_phy = i; @@ -4989,18 +5033,16 @@ struct rtw89_txtime_data { bool reenable; }; -static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_txtime_data *iter_data) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_txtime_data *iter_data = - (struct rtw89_txtime_data *)data; struct rtw89_dev *rtwdev = iter_data->rtwdev; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_cx *cx = &btc->cx; struct rtw89_btc_wl_info *wl = &cx->wl; struct rtw89_btc_wl_link_info *plink = NULL; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 tx_time = iter_data->tx_time; u8 tx_retry = iter_data->tx_retry; u16 enable = iter_data->enable; @@ -5023,8 +5065,8 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* backup the original tx time before tx-limit on */ if (reenable) { - rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); - rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); + rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); + rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); @@ -5032,22 +5074,37 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* restore the original tx time if no tx-limit */ if (!enable) { - rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); } else { - rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", __func__, tx_time, tx_retry); } } +static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_txtime_data *iter_data = + (struct rtw89_txtime_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -5231,8 +5288,14 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; + struct rtw89_btc_dm *dm = &btc->dm; u8 profile_map = 0; + if (dm->freerun_chk) { + _action_freerun(rtwdev); + return; + } + if (bt_linfo->hfp_desc.exist) profile_map |= BTC_BT_HFP; @@ -5247,30 +5310,20 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) switch (profile_map) { case BTC_BT_NOPROFILE: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (pan.active) + if (pan.active) _action_bt_pan(rtwdev); else _action_bt_idle(rtwdev); break; case BTC_BT_HFP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hfp(rtwdev); + _action_bt_hfp(rtwdev); break; case BTC_BT_HFP | BTC_BT_HID: case BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hid(rtwdev); + _action_bt_hid(rtwdev); break; case BTC_BT_A2DP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (a2dp.sink) + if (a2dp.sink) _action_bt_a2dpsink(rtwdev); else if (bt_linfo->multi_link.now && !hid.pair_cnt) _action_bt_a2dp_pan(rtwdev); @@ -5283,13 +5336,18 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_HFP: case BTC_BT_A2DP | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else if (pan.active) + _action_bt_a2dp_pan_hid(rtwdev); else _action_bt_a2dp_hid(rtwdev); break; case BTC_BT_A2DP | BTC_BT_PAN: - _action_bt_a2dp_pan(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan(rtwdev); break; case BTC_BT_PAN | BTC_BT_HFP: case BTC_BT_PAN | BTC_BT_HID: @@ -5299,7 +5357,10 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: default: - _action_bt_a2dp_pan_hid(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan_hid(rtwdev); break; } } @@ -5319,7 +5380,7 @@ static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) policy_type = BTC_CXP_OFFE_WL; else if (btc->cx.wl.status.val & btc_scanning_map.val) policy_type = BTC_CXP_OFFE_2GBWMIXB; - else if (btc->cx.bt.link_info.profile_cnt.now == 0) + else if (btc->cx.bt.link_info.status.map.connect == 0) policy_type = BTC_CXP_OFFE_2GISOB; else policy_type = BTC_CXP_OFFE_2GBWISOB; @@ -6891,6 +6952,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) bt->scan_rx_low_pri = false; igno_bt = false; + dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ + if (always_freerun) { _action_freerun(rtwdev); igno_bt = true; @@ -6929,18 +6992,9 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) goto exit; } - if (cx->state_map == BTC_WLINKING) { - if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || - mode == BTC_WLINK_5G) { - _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; - goto exit; - } - } - - if (wl->status.map.scan) { + if (wl->status.val & btc_scanning_map.val) { _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; + bt->scan_rx_low_pri = true; goto exit; } @@ -7176,10 +7230,6 @@ void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; - wl->scan_info.band[phy_idx] = band; - wl->scan_info.phy_map |= BIT(phy_idx); - _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); - if (rtwdev->dbcc_en) { wl->dbcc_info.scan_band[phy_idx] = band; _update_dbcc_band(rtwdev, phy_idx); @@ -7374,13 +7424,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) "[BTC], %s(): bt_info[2]=0x%02x\n", __func__, bt->raw_info[2]); - /* reset to mo-connect before update */ - b->status.val = BTC_BLINK_NOCONNECT; b->profile_cnt.last = b->profile_cnt.now; - b->relink.last = b->relink.now; - a2dp->exist_last = a2dp->exist; - b->multi_link.last = b->multi_link.now; - bt->inq_pag.last = bt->inq_pag.now; b->profile_cnt.now = 0; hid->type = 0; @@ -7399,7 +7443,8 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->profile_cnt.now += (u8)hid->exist; a2dp->exist = btinfo.lb2.a2dp; b->profile_cnt.now += (u8)a2dp->exist; - pan->active = btinfo.lb2.pan; + pan->exist = btinfo.lb2.pan; + b->profile_cnt.now += (u8)pan->exist; btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); /* parse raw info low-Byte3 */ @@ -7423,8 +7468,14 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte1 */ btinfo.val = bt->raw_info[BTC_BTINFO_H1]; b->status.map.ble_connect = btinfo.hb1.ble_connect; - if (btinfo.hb1.ble_connect) - hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); + if (btinfo.hb1.ble_connect) { + if (hid->exist) + hid->type |= BTC_HID_BLE; + else if (btinfo.hb1.voice) + hid->type |= BTC_HID_RCU_VOICE; + else + hid->type |= BTC_HID_RCU; + } cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); bt->reinit = btinfo.hb1.reinit; @@ -7436,7 +7487,6 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) if (bt->igno_wl && !cx->wl.status.map.rf_off) _set_bt_ignore_wlan_act(rtwdev, false); - hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); bt->ble_scan_en = btinfo.hb1.ble_scan; cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); @@ -7446,8 +7496,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte2 */ btinfo.val = bt->raw_info[BTC_BTINFO_H2]; - pan->exist = btinfo.hb2.pan_active; - b->profile_cnt.now += (u8)pan->exist; + pan->active = !!btinfo.hb2.pan_active; cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); b->afh_update = btinfo.hb2.afh_update; @@ -7455,8 +7504,9 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->slave_role = btinfo.hb2.slave; hid->slot_info = btinfo.hb2.hid_slot; hid->pair_cnt = btinfo.hb2.hid_cnt; - hid->type |= (hid->slot_info == BTC_HID_218 ? - BTC_HID_218 : BTC_HID_418); + if (!b->status.map.ble_connect || hid->pair_cnt > 1) + hid->type |= (hid->slot_info == BTC_HID_218 ? + BTC_HID_218 : BTC_HID_418); /* parse raw info high-Byte3 */ btinfo.val = bt->raw_info[BTC_BTINFO_H3]; a2dp->bitpool = btinfo.hb3.a2dp_bitpool; @@ -7479,13 +7529,16 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); } -void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, enum btc_role_state state) +void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + enum btc_role_state state) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; struct rtw89_btc *btc = &rtwdev->btc; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; @@ -7493,51 +7546,59 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif struct rtw89_btc_wl_link_info *wlinfo = NULL; u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], role is STA=%d\n", vif->type == NL80211_IFTYPE_STATION); - rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", chan->band_type, chan->channel, chan->band_width); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", state == BTC_ROLE_MSTS_STA_CONN_END); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], bcn_period=%d dtim_period=%d\n", - vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); + bss_conf->beacon_int, bss_conf->dtim_period); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); - if (rtwsta) { rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", - rtwsta->mac_id); + rtwsta_link->mac_id); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA support HE=%d VHT=%d HT=%d\n", - sta->deflink.he_cap.has_he, - sta->deflink.vht_cap.vht_supported, - sta->deflink.ht_cap.ht_supported); - if (sta->deflink.he_cap.has_he) + link_sta->he_cap.has_he, + link_sta->vht_cap.vht_supported, + link_sta->ht_cap.ht_supported); + if (link_sta->he_cap.has_he) mode |= BIT(BTC_WL_MODE_HE); - if (sta->deflink.vht_cap.vht_supported) + if (link_sta->vht_cap.vht_supported) mode |= BIT(BTC_WL_MODE_VHT); - if (sta->deflink.ht_cap.ht_supported) + if (link_sta->ht_cap.ht_supported) mode |= BIT(BTC_WL_MODE_HT); r.mode = mode; } - if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) + if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { + rcu_read_unlock(); return; + } rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC], wifi_role=%d\n", rtwvif->wifi_role); + "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); - r.role = rtwvif->wifi_role; - r.phy = rtwvif->phy_idx; - r.pid = rtwvif->port; + r.role = rtwvif_link->wifi_role; + r.phy = rtwvif_link->phy_idx; + r.pid = rtwvif_link->port; r.active = true; r.connected = MLME_LINKED; - r.bcn_period = vif->bss_conf.beacon_int; - r.dtim_period = vif->bss_conf.dtim_period; + r.bcn_period = bss_conf->beacon_int; + r.dtim_period = bss_conf->dtim_period; r.band = chan->band_type; r.ch = chan->channel; r.bw = chan->band_width; @@ -7545,10 +7606,12 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif r.chdef.center_ch = chan->channel; r.chdef.bw = chan->band_width; r.chdef.chan = chan->primary_channel; - ether_addr_copy(r.mac_addr, rtwvif->mac_addr); + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + + rcu_read_unlock(); - if (rtwsta && vif->type == NL80211_IFTYPE_STATION) - r.mac_id = rtwsta->mac_id; + if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) + r.mac_id = rtwsta_link->mac_id; btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; @@ -7779,26 +7842,26 @@ struct rtw89_btc_wl_sta_iter_data { bool is_traffic_change; }; -static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +static +void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_btc_wl_sta_iter_data *iter_data) { - struct rtw89_btc_wl_sta_iter_data *iter_data = - (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_dev *rtwdev = iter_data->rtwdev; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_link_info *link_info = NULL; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_traffic_stats *link_info_t = NULL; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_traffic_stats *stats = &rtwvif->stats; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_btc_wl_role_info *r; struct rtw89_btc_wl_role_info_v1 *r1; u32 last_tx_rate, last_rx_rate; u16 last_tx_lvl, last_rx_lvl; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u8 rssi; u8 busy = 0; u8 dir = 0; @@ -7806,11 +7869,11 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) u8 i = 0; bool is_sta_change = false, is_traffic_change = false; - rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); link_info = &wl->link_info[port]; - link_info->stat.traffic = rtwvif->stats; + link_info->stat.traffic = *stats; link_info_t = &link_info->stat.traffic; if (link_info->connected == MLME_NO_LINK) { @@ -7858,19 +7921,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->busy_all |= busy; iter_data->dir_all |= BIT(dir); - if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && + if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && last_rx_rate > RTW89_HW_RATE_CCK2 && link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) link_info->rx_rate_drop_cnt++; - if (last_tx_rate != rtwsta->ra_report.hw_rate || - last_rx_rate != rtwsta->rx_hw_rate || + if (last_tx_rate != rtwsta_link->ra_report.hw_rate || + last_rx_rate != rtwsta_link->rx_hw_rate || last_tx_lvl != link_info_t->tx_tfc_lv || last_rx_lvl != link_info_t->rx_tfc_lv) is_traffic_change = true; - link_info_t->tx_rate = rtwsta->ra_report.hw_rate; - link_info_t->rx_rate = rtwsta->rx_hw_rate; + link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; + link_info_t->rx_rate = rtwsta_link->rx_hw_rate; if (link_info->role == RTW89_WIFI_ROLE_STATION || link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { @@ -7882,19 +7945,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) r = &wl->role_info; r->active_role[port].tx_lvl = stats->tx_tfc_lv; r->active_role[port].rx_lvl = stats->rx_tfc_lv; - r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; - r->active_role[port].rx_rate = rtwsta->rx_hw_rate; + r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 1) { r1 = &wl->role_info_v1; r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; - r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; - r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; + r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 2) { dm->trx_info.tx_lvl = stats->tx_tfc_lv; dm->trx_info.rx_lvl = stats->rx_tfc_lv; - dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; - dm->trx_info.rx_rate = rtwsta->rx_hw_rate; + dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; + dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; } dm->trx_info.tx_tp = link_info_t->tx_throughput; @@ -7914,6 +7977,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->is_traffic_change = true; } +static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_btc_wl_sta_iter_data *iter_data = + (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + #define BTC_NHM_CHK_INTVL 20 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) @@ -7963,6 +8041,53 @@ void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) } } +static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) +{ + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + + switch (func) { + case BTF_EVNT_RPT: + case BTF_EVNT_BT_INFO: + case BTF_EVNT_BT_SCBD: + case BTF_EVNT_BT_REG: + case BTF_EVNT_CX_RUNINFO: + case BTF_EVNT_BT_PSD: + return func; + case BTF_EVNT_BT_DEV_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_BUF_OVERFLOW; + else + return BTF_EVNT_BT_DEV_INFO; + case BTF_EVNT_BT_LEAUDIO_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_BUF_OVERFLOW; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_BUF_OVERFLOW: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_MAX; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_C2H_LOOPBACK: + if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_MAX: + default: + return BTF_EVNT_MAX; + } +} + void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func) { @@ -7979,10 +8104,14 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (class != BTFC_FW_EVENT) return; + func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); + switch (func) { - case BTF_EVNT_RPT: case BTF_EVNT_BUF_OVERFLOW: pfwinfo->event[func]++; + break; + case BTF_EVNT_RPT: + pfwinfo->event[func]++; /* Don't need rtw89_leave_ps_mode() */ btc_fw_event(rtwdev, func, buf, len); break; diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index de53b56632f7..dbdb56e063ef 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -271,8 +271,10 @@ void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work); void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work); -void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, enum btc_role_state state); +void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + enum btc_role_state state); void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state); void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, enum btc_wl_rfk_type type, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 4553810634c6..bba5bde95bb4 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -352,10 +352,6 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; bool entity_active; - entity_active = rtw89_get_entity_state(rtwdev); - if (!entity_active) - return; - mode = rtw89_get_entity_mode(rtwdev); switch (mode) { case RTW89_ENTITY_MODE_SCC: @@ -375,6 +371,11 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) chanctx_idx = roc_idx; phy_idx = RTW89_PHY_0; + + entity_active = rtw89_get_entity_state(rtwdev, phy_idx); + if (!entity_active) + return; + chan = rtw89_chan_get(rtwdev, chanctx_idx); chip->ops->set_txpwr(rtwdev, chan, phy_idx); } @@ -393,8 +394,6 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; bool entity_active; - entity_active = rtw89_get_entity_state(rtwdev); - mode = rtw89_entity_recalc(rtwdev); switch (mode) { case RTW89_ENTITY_MODE_SCC: @@ -416,6 +415,8 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) mac_idx = RTW89_MAC_0; phy_idx = RTW89_PHY_0; + entity_active = rtw89_get_entity_state(rtwdev, phy_idx); + chan = rtw89_chan_get(rtwdev, chanctx_idx); chan_rcd = rtw89_chan_rcd_get(rtwdev, chanctx_idx); @@ -432,19 +433,10 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) rtw89_chip_rfk_band_changed(rtwdev, phy_idx, chan); } - rtw89_set_entity_state(rtwdev, true); + rtw89_set_entity_state(rtwdev, phy_idx, true); return 0; } -void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_chan *chan) -{ - const struct cfg80211_chan_def *chandef; - - chandef = rtw89_chandef_get(rtwdev, rtwvif->chanctx_idx); - rtw89_get_channel_params(chandef, chan); -} - static enum rtw89_core_tx_type rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, struct sk_buff *skb) @@ -463,8 +455,9 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req, enum btc_pkt_type pkt_type) { - struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct ieee80211_link_sta *link_sta; struct sk_buff *skb = tx_req->skb; struct rtw89_sta *rtwsta; u8 ampdu_num; @@ -478,21 +471,26 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU)) return; - if (!sta) { + if (!rtwsta_link) { rtw89_warn(rtwdev, "cannot set ampdu info without sta\n"); return; } tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - rtwsta = (struct rtw89_sta *)sta->drv_priv; + rtwsta = rtwsta_link->rtwsta; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ? rtwsta->ampdu_params[tid].agg_num : - 4 << sta->deflink.ht_cap.ampdu_factor) - 1); + 4 << link_sta->ht_cap.ampdu_factor) - 1); desc_info->agg_en = true; - desc_info->ampdu_density = sta->deflink.ht_cap.ampdu_density; + desc_info->ampdu_density = link_sta->ht_cap.ampdu_density; desc_info->ampdu_num = ampdu_num; + + rcu_read_unlock(); } static void @@ -569,9 +567,13 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan) { struct sk_buff *skb = tx_req->skb; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = tx_info->control.vif; + struct ieee80211_bss_conf *bss_conf; u16 lowest_rate; + u16 rate; if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE || (vif && vif->p2p)) @@ -581,25 +583,35 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta) + if (!rtwvif_link) return lowest_rate; - return __ffs(vif->bss_conf.basic_rates) + lowest_rate; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->basic_rates || !rtwsta_link) { + rate = lowest_rate; + goto out; + } + + rate = __ffs(bss_conf->basic_rates) + lowest_rate; + +out: + rcu_read_unlock(); + + return rate; } static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; - if (!sta) - return rtwvif->mac_id; + if (!rtwsta_link) + return rtwvif_link->mac_id; - rtwsta = (struct rtw89_sta *)sta->drv_priv; - return rtwsta->mac_id; + return rtwsta_link->mac_id; } static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev, @@ -618,11 +630,10 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); struct sk_buff *skb = tx_req->skb; u8 qsel, ch_dma; @@ -631,7 +642,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, desc_info->qsel = qsel; desc_info->ch_dma = ch_dma; - desc_info->port = desc_info->hiq ? rtwvif->port : 0; + desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL; desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE; @@ -701,26 +712,36 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req, enum btc_pkt_type pkt_type) { - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct sk_buff *skb = tx_req->skb; struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_link_sta *link_sta; __le16 fc = hdr->frame_control; /* AP IOT issue with EAPoL, ARP and DHCP */ if (pkt_type < PACKET_MAX) return false; - if (!sta || !sta->deflink.he_cap.has_he) + if (!rtwsta_link) return false; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (!link_sta->he_cap.has_he) { + rcu_read_unlock(); + return false; + } + + rcu_read_unlock(); + if (!ieee80211_is_data_qos(fc)) return false; if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN) return false; - if (rtwsta && rtwsta->ra_report.might_fallback_legacy) + if (rtwsta_link && rtwsta_link->ra_report.might_fallback_legacy) return false; return true; @@ -730,8 +751,7 @@ static void __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct sk_buff *skb = tx_req->skb; struct ieee80211_hdr *hdr = (void *)skb->data; __le16 fc = hdr->frame_control; @@ -747,7 +767,7 @@ __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, hdr = data; htc = data + hdr_len; hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_ORDER); - *htc = rtwsta->htc_template ? rtwsta->htc_template : + *htc = rtwsta_link->htc_template ? rtwsta_link->htc_template : le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) | le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_CAS, RTW89_HTC_MASK_CTL_ID); @@ -761,8 +781,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, enum btc_pkt_type pkt_type) { struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type)) goto desc_bk; @@ -773,23 +792,25 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, desc_info->a_ctrl_bsr = true; desc_bk: - if (!rtwvif || rtwvif->last_a_ctrl == desc_info->a_ctrl_bsr) + if (!rtwvif_link || rtwvif_link->last_a_ctrl == desc_info->a_ctrl_bsr) return; - rtwvif->last_a_ctrl = desc_info->a_ctrl_bsr; + rtwvif_link->last_a_ctrl = desc_info->a_ctrl_bsr; desc_info->bk = true; } static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; - enum rtw89_chanctx_idx idx = rtwvif->chanctx_idx; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx); + struct ieee80211_link_sta *link_sta; u16 lowest_rate; + u16 rate; if (rate_pattern->enable) return rate_pattern->rate; @@ -801,20 +822,31 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - if (!sta || !sta->deflink.supp_rates[chan->band_type]) + if (!rtwsta_link) return lowest_rate; - return __ffs(sta->deflink.supp_rates[chan->band_type]) + lowest_rate; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (!link_sta->supp_rates[chan->band_type]) { + rate = lowest_rate; + goto out; + } + + rate = __ffs(link_sta->supp_rates[chan->band_type]) + lowest_rate; + +out: + rcu_read_unlock(); + + return rate; } static void rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; struct sk_buff *skb = tx_req->skb; u8 tid, tid_indicate; @@ -829,10 +861,10 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, desc_info->tid_indicate = tid_indicate; desc_info->qsel = qsel; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); - desc_info->port = desc_info->hiq ? rtwvif->port : 0; - desc_info->er_cap = rtwsta ? rtwsta->er_cap : false; - desc_info->stbc = rtwsta ? rtwsta->ra.stbc_cap : false; - desc_info->ldpc = rtwsta ? rtwsta->ra.ldpc_cap : false; + desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; + desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false; + desc_info->stbc = rtwsta_link ? rtwsta_link->ra.stbc_cap : false; + desc_info->ldpc = rtwsta_link ? rtwsta_link->ra.ldpc_cap : false; /* enable wd_info for AMPDU */ desc_info->en_wd_info = true; @@ -1027,13 +1059,34 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev, int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel) { + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_core_tx_request tx_req = {0}; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_vif_link *rtwvif_link; int ret; + /* By default, driver writes tx via the link on HW-0. And then, + * according to links' status, HW can change tx to another link. + */ + + if (rtwsta) { + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "tx: find no sta link on HW-0\n"); + return -ENOLINK; + } + } + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "tx: find no vif link on HW-0\n"); + return -ENOLINK; + } + tx_req.skb = skb; - tx_req.sta = sta; - tx_req.vif = vif; + tx_req.rtwvif_link = rtwvif_link; + tx_req.rtwsta_link = rtwsta_link; rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); @@ -1514,16 +1567,24 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate) static void rtw89_core_rx_process_phy_ppdu_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_dev *rtwdev = rtwsta->rtwdev; struct rtw89_hal *hal = &rtwdev->hal; + struct rtw89_sta_link *rtwsta_link; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; u8 ant_pos = U8_MAX; u8 evm_pos = 0; int i; - if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; + + if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) return; if (hal->ant_diversity && hal->antenna_rx) { @@ -1531,22 +1592,24 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data, evm_pos = ant_pos; } - ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); + ewma_rssi_add(&rtwsta_link->avg_rssi, phy_ppdu->rssi_avg); if (ant_pos < ant_num) { - ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]); + ewma_rssi_add(&rtwsta_link->rssi[ant_pos], phy_ppdu->rssi[0]); } else { for (i = 0; i < rtwdev->chip->rf_path_num; i++) - ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]); + ewma_rssi_add(&rtwsta_link->rssi[i], phy_ppdu->rssi[i]); } if (phy_ppdu->ofdm.has && (phy_ppdu->has_data || phy_ppdu->has_bcn)) { - ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr); + ewma_snr_add(&rtwsta_link->avg_snr, phy_ppdu->ofdm.avg_snr); if (rtw89_get_data_rate_nss(rtwdev, phy_ppdu->rate) == 1) { - ewma_evm_add(&rtwsta->evm_1ss, phy_ppdu->ofdm.evm_min); + ewma_evm_add(&rtwsta_link->evm_1ss, phy_ppdu->ofdm.evm_min); } else { - ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min); - ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max); + ewma_evm_add(&rtwsta_link->evm_min[evm_pos], + phy_ppdu->ofdm.evm_min); + ewma_evm_add(&rtwsta_link->evm_max[evm_pos], + phy_ppdu->ofdm.evm_max); } } } @@ -1876,17 +1939,19 @@ struct rtw89_vif_rx_stats_iter_data { }; static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct sk_buff *skb) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u8 *pos, *end, type, tf_bw; u16 aid, tf_rua; - if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || - rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || - rtwvif->net_type == RTW89_NET_TYPE_NO_LINK) + if (!ether_addr_equal(bss_conf->bssid, tf->ta) || + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || + rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK) return; type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK); @@ -1915,7 +1980,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, rtwdev->stats.rx_tf_acc++; if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ && rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106) - rtwvif->pwr_diff_en = true; + rtwvif_link->pwr_diff_en = true; break; } @@ -1986,7 +2051,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work); } -static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, +static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link, struct ieee80211_hdr *hdr, size_t len) { struct ieee80211_mgmt *mgmt = (typeof(mgmt))hdr; @@ -1994,20 +2059,22 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, if (len < offsetof(typeof(*mgmt), u.beacon.variable)) return; - WRITE_ONCE(rtwvif->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); + WRITE_ONCE(rtwvif_link->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); } static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_vif_rx_stats_iter_data *iter_data = data; struct rtw89_dev *rtwdev = iter_data->rtwdev; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; struct sk_buff *skb = iter_data->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu; + struct ieee80211_bss_conf *bss_conf; + struct rtw89_vif_link *rtwvif_link; const u8 *bssid = iter_data->bssid; if (rtwdev->scanning && @@ -2015,33 +2082,49 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, ieee80211_is_probe_resp(hdr->frame_control))) rtw89_core_cancel_6ghz_probe_tx(rtwdev, skb); - if (!vif->bss_conf.bssid) - return; + rcu_read_lock(); + + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) + goto out; + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->bssid) + goto out; if (ieee80211_is_trigger(hdr->frame_control)) { - rtw89_stats_trigger_frame(rtwdev, vif, skb); - return; + rtw89_stats_trigger_frame(rtwdev, rtwvif_link, bss_conf, skb); + goto out; } - if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) - return; + if (!ether_addr_equal(bss_conf->bssid, bssid)) + goto out; if (ieee80211_is_beacon(hdr->frame_control)) { if (vif->type == NL80211_IFTYPE_STATION && !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) { - rtw89_vif_sync_bcn_tsf(rtwvif, hdr, skb->len); + rtw89_vif_sync_bcn_tsf(rtwvif_link, hdr, skb->len); rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu); } pkt_stat->beacon_nr++; + + if (phy_ppdu) + ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg); } - if (!ether_addr_equal(vif->addr, hdr->addr1)) - return; + if (!ether_addr_equal(bss_conf->addr, hdr->addr1)) + goto out; if (desc_info->data_rate < RTW89_HW_RATE_NR) pkt_stat->rx_rate_cnt[desc_info->data_rate]++; rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); + +out: + rcu_read_unlock(); } static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, @@ -2432,15 +2515,23 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta) struct rtw89_core_iter_rx_status *iter_data = (struct rtw89_core_iter_rx_status *)data; struct ieee80211_rx_status *rx_status = iter_data->rx_status; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; u8 mac_id = iter_data->mac_id; - if (mac_id != rtwsta->mac_id) + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; + + if (mac_id != rtwsta_link->mac_id) return; - rtwsta->rx_status = *rx_status; - rtwsta->rx_hw_rate = desc_info->data_rate; + rtwsta_link->rx_status = *rx_status; + rtwsta_link->rx_hw_rate = desc_info->data_rate; } static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev, @@ -2546,6 +2637,10 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; + /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */ + if (rtwdev->support_mlo) + return RTW89_PS_MODE_NONE; + if (rtw89_disable_ps_mode || !chip->ps_mode_supported || RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) return RTW89_PS_MODE_NONE; @@ -2658,7 +2753,7 @@ static void rtw89_core_ba_work(struct work_struct *work) list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); u8 tid = txq->tid; if (!sta) { @@ -2686,8 +2781,8 @@ skip_ba_work: spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { struct rtw89_txq *rtwtxq, *tmp; @@ -2701,8 +2796,8 @@ static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { struct rtw89_txq *rtwtxq, *tmp; @@ -2718,10 +2813,10 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct sk_buff *skb, *tmp; skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { @@ -2762,7 +2857,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, struct ieee80211_hw *hw = rtwdev->hw; struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) return; @@ -2838,10 +2933,19 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, bool *sched_txq, bool *reinvoke) { struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; - struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(txq->sta); + struct rtw89_sta_link *rtwsta_link; - if (!sta || rtwsta->max_agg_wait <= 0) + if (!rtwsta) + return false; + + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "agg wait: find no link on HW-0\n"); + return false; + } + + if (rtwsta_link->max_agg_wait <= 0) return false; if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID) @@ -2855,7 +2959,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, return false; } - if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta->max_agg_wait) { + if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta_link->max_agg_wait) { *reinvoke = true; rtwtxq->wait_cnt++; return true; @@ -2879,7 +2983,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv ieee80211_txq_schedule_start(hw, ac); while ((txq = ieee80211_next_txq(hw, ac))) { rtwtxq = (struct rtw89_txq *)txq->drv_priv; - rtwvif = (struct rtw89_vif *)txq->vif->drv_priv; + rtwvif = vif_to_rtwvif(txq->vif); if (rtwvif->offchan) { ieee80211_return_txq(hw, txq, true); @@ -2955,16 +3059,23 @@ static void rtw89_forbid_ba_work(struct work_struct *w) static void rtw89_core_sta_pending_tx_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif_target = data, *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_vif_link *target = data; + struct rtw89_vif_link *rtwvif_link; struct sk_buff *skb, *tmp; + unsigned int link_id; int qsel, ret; - if (rtwvif->chanctx_idx != rtwvif_target->chanctx_idx) - return; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->chanctx_idx == target->chanctx_idx) + goto bottom; + + return; +bottom: if (skb_queue_len(&rtwsta->roc_queue) == 0) return; @@ -2982,17 +3093,17 @@ static void rtw89_core_sta_pending_tx_iter(void *data, } static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_core_sta_pending_tx_iter, - rtwvif); + rtwvif_link); } static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool qos, bool ps) + struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; struct sk_buff *skb; @@ -3002,7 +3113,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, return 0; rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + sta = ieee80211_find_sta(vif, vif->cfg.ap_addr); if (!sta) { ret = -EINVAL; goto out; @@ -3040,31 +3151,48 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; + struct rtw89_vif_link *rtwvif_link; struct cfg80211_chan_def roc_chan; - struct rtw89_vif *tmp; + struct rtw89_vif *tmp_vif; + u32 reg; int ret; lockdep_assert_held(&rtwdev->mutex); rtw89_leave_ips_by_hwflags(rtwdev); rtw89_leave_lps(rtwdev); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "roc start: find no link on HW-0\n"); + return; + } + rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-1 failed: %d\n", ret); - rtw89_for_each_rtwvif(rtwdev, tmp) - if (tmp->chanctx_idx == rtwvif->chanctx_idx) - tmp->offchan = true; + rtw89_for_each_rtwvif(rtwdev, tmp_vif) { + struct rtw89_vif_link *tmp_link; + unsigned int link_id; + + rtw89_vif_for_each_link(tmp_vif, tmp_link, link_id) { + if (tmp_link->chanctx_idx == rtwvif_link->chanctx_idx) { + tmp_vif->offchan = true; + break; + } + } + } cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT); - rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, &roc_chan); + rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan); rtw89_set_channel(rtwdev); - rtw89_write32_clr(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_clr(rtwdev, reg, B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); ieee80211_ready_on_channel(hw); cancel_delayed_work(&rtwvif->roc.roc_work); @@ -3077,7 +3205,9 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; - struct rtw89_vif *tmp; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *tmp_vif; + u32 reg; int ret; lockdep_assert_held(&rtwdev->mutex); @@ -3087,24 +3217,27 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_leave_ips_by_hwflags(rtwdev); rtw89_leave_lps(rtwdev); - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rtwdev->hal.rx_fltr); + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "roc end: find no link on HW-0\n"); + return; + } + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); roc->state = RTW89_ROC_IDLE; - rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, NULL); + rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL); rtw89_chanctx_proceed(rtwdev); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-0 failed: %d\n", ret); - rtw89_for_each_rtwvif(rtwdev, tmp) - if (tmp->chanctx_idx == rtwvif->chanctx_idx) - tmp->offchan = false; + rtw89_for_each_rtwvif(rtwdev, tmp_vif) + tmp_vif->offchan = false; - rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif); + rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link); queue_work(rtwdev->txq_wq, &rtwdev->txq_work); if (hw->conf.flags & IEEE80211_CONF_IDLE) @@ -3188,39 +3321,52 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; bool tfc_changed; tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); + rtw89_for_each_rtwvif(rtwdev, rtwvif) { rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); - rtw89_fw_h2c_tp_offload(rtwdev, rtwvif); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); } return tfc_changed; } -static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - if ((rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) || - rtwvif->tdls_peer) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) return; - if (rtwvif->offchan) - return; - - if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE && - rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE) - rtw89_enter_lps(rtwdev, rtwvif, true); + rtw89_enter_lps(rtwdev, rtwvif_link, true); } static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + if (rtwvif->tdls_peer) + continue; + if (rtwvif->offchan) + continue; + + if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE || + rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) + continue; - rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_vif_enter_lps(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_vif_enter_lps(rtwdev, rtwvif_link); + } } static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) @@ -3234,14 +3380,16 @@ static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) rtw89_chip_rfk_track(rtwdev); } -void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_P2P_PS_CHANGE); else - rtw89_process_p2p_ps(rtwdev, vif); + rtw89_process_p2p_ps(rtwdev, rtwvif_link, bss_conf); } void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, @@ -3326,7 +3474,8 @@ 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 *rtwsta, u8 tid, u8 *cam_idx) + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_cam_info *cam_info = &rtwdev->cam_info; @@ -3363,7 +3512,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, } entry->tid = tid; - list_add_tail(&entry->list, &rtwsta->ba_cam_list); + list_add_tail(&entry->list, &rtwsta_link->ba_cam_list); *cam_idx = idx; @@ -3371,7 +3520,8 @@ 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 *rtwsta, u8 tid, u8 *cam_idx) + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx) { struct rtw89_cam_info *cam_info = &rtwdev->cam_info; struct rtw89_ba_cam_entry *entry = NULL, *tmp; @@ -3379,7 +3529,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, lockdep_assert_held(&rtwdev->mutex); - list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) { + list_for_each_entry_safe(entry, tmp, &rtwsta_link->ba_cam_list, list) { if (entry->tid != tid) continue; @@ -3396,24 +3546,25 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, #define RTW89_TYPE_MAPPING(_type) \ case NL80211_IFTYPE_ ## _type: \ - rtwvif->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ break -void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) +void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_bss_conf *bss_conf; switch (vif->type) { case NL80211_IFTYPE_STATION: if (vif->p2p) - rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; else - rtwvif->wifi_role = RTW89_WIFI_ROLE_STATION; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_STATION; break; case NL80211_IFTYPE_AP: if (vif->p2p) - rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_GO; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_GO; else - rtwvif->wifi_role = RTW89_WIFI_ROLE_AP; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_AP; break; RTW89_TYPE_MAPPING(ADHOC); RTW89_TYPE_MAPPING(MONITOR); @@ -3426,23 +3577,27 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: - rtwvif->net_type = RTW89_NET_TYPE_AP_MODE; - rtwvif->self_role = RTW89_SELF_ROLE_AP; + rtwvif_link->net_type = RTW89_NET_TYPE_AP_MODE; + rtwvif_link->self_role = RTW89_SELF_ROLE_AP; break; case NL80211_IFTYPE_ADHOC: - rtwvif->net_type = RTW89_NET_TYPE_AD_HOC; - rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; + rtwvif_link->net_type = RTW89_NET_TYPE_AD_HOC; + rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; break; case NL80211_IFTYPE_STATION: if (assoc) { - rtwvif->net_type = RTW89_NET_TYPE_INFRA; - rtwvif->trigger = vif->bss_conf.he_support; + rtwvif_link->net_type = RTW89_NET_TYPE_INFRA; + + rcu_read_lock(); + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + rtwvif_link->trigger = bss_conf->he_support; + rcu_read_unlock(); } else { - rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; - rtwvif->trigger = false; + rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; + rtwvif_link->trigger = false; } - rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; - rtwvif->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; + rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; + rtwvif_link->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; break; case NL80211_IFTYPE_MONITOR: break; @@ -3452,137 +3607,110 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) } } -int rtw89_core_sta_add(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); struct rtw89_hal *hal = &rtwdev->hal; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; int i; int ret; - rtwsta->rtwdev = rtwdev; - rtwsta->rtwvif = rtwvif; - rtwsta->prev_rssi = 0; - INIT_LIST_HEAD(&rtwsta->ba_cam_list); - skb_queue_head_init(&rtwsta->roc_queue); - - for (i = 0; i < ARRAY_SIZE(sta->txq); i++) - rtw89_core_txq_init(rtwdev, sta->txq[i]); - - ewma_rssi_init(&rtwsta->avg_rssi); - ewma_snr_init(&rtwsta->avg_snr); - ewma_evm_init(&rtwsta->evm_1ss); + 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); for (i = 0; i < ant_num; i++) { - ewma_rssi_init(&rtwsta->rssi[i]); - ewma_evm_init(&rtwsta->evm_min[i]); - ewma_evm_init(&rtwsta->evm_max[i]); + ewma_rssi_init(&rtwsta_link->rssi[i]); + ewma_evm_init(&rtwsta_link->evm_min[i]); + ewma_evm_init(&rtwsta_link->evm_max[i]); } if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - /* for station mode, assign the mac_id from itself */ - rtwsta->mac_id = rtwvif->mac_id; - /* must do rtw89_reg_6ghz_recalc() before rfk channel */ - ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); + ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); if (ret) return ret; - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_CONN_START); - rtw89_chip_rfk_channel(rtwdev, rtwvif); + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { - rtwsta->mac_id = rtw89_acquire_mac_id(rtwdev); - if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM) - return -ENOSPC; - - ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false); + ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); if (ret) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); rtw89_warn(rtwdev, "failed to send h2c macid pause\n"); return ret; } - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_CREATE); if (ret) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } - ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) return ret; - ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) return ret; - - rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; } -int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); if (vif->type == NL80211_IFTYPE_STATION) - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false); - - rtwdev->total_sta_assoc--; - if (sta->tdls) - rtwvif->tdls_peer--; - rtwsta->disassoc = true; + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); return 0; } -int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); int ret; - rtw89_mac_bf_monitor_calc(rtwdev, sta, true); - rtw89_mac_bf_disassoc(rtwdev, vif, sta); - rtw89_core_free_sta_pending_ba(rtwdev, sta); - rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); - rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true); + rtw89_mac_bf_disassoc(rtwdev, rtwvif_link, rtwsta_link); if (vif->type == NL80211_IFTYPE_AP || sta->tdls) - rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); + rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); if (sta->tdls) - rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); + rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - rtw89_vif_type_mapping(vif, false); - rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, true); + rtw89_vif_type_mapping(rtwvif_link, false); + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true); } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); return ret; } - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, true); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -3591,106 +3719,114 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, return ret; } -int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); int ret; if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { if (sta->tdls) { - ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, sta->addr); + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, + link_sta->addr); if (ret) { rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n"); + rcu_read_unlock(); return ret; } + + rcu_read_unlock(); } - ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, bssid_cam); + ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta_link->addr_cam, bssid_cam); if (ret) { rtw89_warn(rtwdev, "failed to send h2c init addr cam\n"); return ret; } } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); return ret; } - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, false); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } - rtwdev->total_sta_assoc++; - if (sta->tdls) - rtwvif->tdls_peer++; - rtw89_phy_ra_assoc(rtwdev, sta); - rtw89_mac_bf_assoc(rtwdev, vif, sta); - rtw89_mac_bf_monitor_calc(rtwdev, sta, false); + rtw89_phy_ra_assoc(rtwdev, rtwsta_link); + rtw89_mac_bf_assoc(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, false); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); if (bss_conf->he_support && !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) - rtwsta->er_cap = true; + rtwsta_link->er_cap = true; - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rcu_read_unlock(); + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_CONN_END); - rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan); - rtw89_phy_ul_tb_assoc(rtwdev, rtwvif); + rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan); + rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); + ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); if (ret) { rtw89_warn(rtwdev, "failed to send h2c general packet\n"); return ret; } - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); } return ret; } -int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); int ret; if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - rtw89_reg_6ghz_recalc(rtwdev, rtwvif, false); - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false); + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_DIS_CONN); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); - - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_REMOVE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } - - rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; @@ -4152,15 +4288,16 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev) void rtw89_core_update_beacon_work(struct work_struct *work) { struct rtw89_dev *rtwdev; - struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, - update_beacon_work); + struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, + update_beacon_work); - if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) return; - rtwdev = rtwvif->rtwdev; + rtwdev = rtwvif_link->rtwvif->rtwdev; + mutex_lock(&rtwdev->mutex); - rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); mutex_unlock(&rtwdev->mutex); } @@ -4266,8 +4403,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_phy_dm_init(rtwdev); - rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); - rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + rtw89_mac_cfg_ppdu_status_bands(rtwdev, true); + rtw89_mac_update_rts_threshold(rtwdev); rtw89_tas_reset(rtwdev); @@ -4355,6 +4492,168 @@ void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id) clear_bit(mac_id, rtwdev->mac_id_map); } +void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + u8 mac_id, u8 port) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 support_link_num = chip->support_link_num; + u8 support_mld_num = 0; + unsigned int link_id; + u8 index; + + bitmap_zero(rtwvif->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + rtwvif->links[link_id] = NULL; + + rtwvif->rtwdev = rtwdev; + + if (rtwdev->support_mlo) { + rtwvif->links_inst_valid_num = support_link_num; + support_mld_num = chip->support_macid_num / support_link_num; + } else { + rtwvif->links_inst_valid_num = 1; + } + + for (index = 0; index < rtwvif->links_inst_valid_num; index++) { + struct rtw89_vif_link *inst = &rtwvif->links_inst[index]; + + inst->rtwvif = rtwvif; + inst->mac_id = mac_id + index * support_mld_num; + inst->mac_idx = RTW89_MAC_0 + index; + inst->phy_idx = RTW89_PHY_0 + index; + + /* multi-link use the same port id on different HW bands */ + inst->port = port; + } +} + +void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta, u8 mac_id) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 support_link_num = chip->support_link_num; + u8 support_mld_num = 0; + unsigned int link_id; + u8 index; + + bitmap_zero(rtwsta->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + rtwsta->links[link_id] = NULL; + + rtwsta->rtwdev = rtwdev; + rtwsta->rtwvif = rtwvif; + + if (rtwdev->support_mlo) { + rtwsta->links_inst_valid_num = support_link_num; + support_mld_num = chip->support_macid_num / support_link_num; + } else { + rtwsta->links_inst_valid_num = 1; + } + + for (index = 0; index < rtwsta->links_inst_valid_num; index++) { + struct rtw89_sta_link *inst = &rtwsta->links_inst[index]; + + inst->rtwvif_link = &rtwvif->links_inst[index]; + + inst->rtwsta = rtwsta; + inst->mac_id = mac_id + index * support_mld_num; + } +} + +struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, + unsigned int link_id) +{ + struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; + u8 index; + int ret; + + if (rtwvif_link) + return rtwvif_link; + + index = find_first_zero_bit(rtwvif->links_inst_map, + rtwvif->links_inst_valid_num); + if (index == rtwvif->links_inst_valid_num) { + ret = -EBUSY; + goto err; + } + + rtwvif_link = &rtwvif->links_inst[index]; + rtwvif_link->link_id = link_id; + + set_bit(index, rtwvif->links_inst_map); + rtwvif->links[link_id] = rtwvif_link; + return rtwvif_link; + +err: + rtw89_err(rtwvif->rtwdev, "vif (link_id %u) failed to set link: %d\n", + link_id, ret); + return NULL; +} + +void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id) +{ + struct rtw89_vif_link **container = &rtwvif->links[link_id]; + struct rtw89_vif_link *link = *container; + u8 index; + + if (!link) + return; + + index = rtw89_vif_link_inst_get_index(link); + clear_bit(index, rtwvif->links_inst_map); + *container = NULL; +} + +struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, + unsigned int link_id) +{ + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; + struct rtw89_sta_link *rtwsta_link = rtwsta->links[link_id]; + u8 index; + int ret; + + if (rtwsta_link) + return rtwsta_link; + + if (!rtwvif_link) { + ret = -ENOLINK; + goto err; + } + + index = rtw89_vif_link_inst_get_index(rtwvif_link); + if (test_bit(index, rtwsta->links_inst_map)) { + ret = -EBUSY; + goto err; + } + + rtwsta_link = &rtwsta->links_inst[index]; + rtwsta_link->link_id = link_id; + + set_bit(index, rtwsta->links_inst_map); + rtwsta->links[link_id] = rtwsta_link; + return rtwsta_link; + +err: + rtw89_err(rtwsta->rtwdev, "sta (link_id %u) failed to set link: %d\n", + link_id, ret); + return NULL; +} + +void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id) +{ + struct rtw89_sta_link **container = &rtwsta->links[link_id]; + struct rtw89_sta_link *link = *container; + u8 index; + + if (!link) + return; + + index = rtw89_sta_link_inst_get_index(link); + clear_bit(index, rtwsta->links_inst_map); + *container = NULL; +} + int rtw89_core_init(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -4444,39 +4743,45 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_core_deinit); -void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, const u8 *mac_addr, bool hw_scan) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); rtwdev->scanning = true; rtw89_leave_lps(rtwdev); if (hw_scan) rtw89_leave_ips_by_hwflags(rtwdev); - ether_addr_copy(rtwvif->mac_addr, mac_addr); - rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type); - rtw89_chip_rfk_scan(rtwdev, rtwvif, true); + ether_addr_copy(rtwvif_link->mac_addr, mac_addr); + rtw89_btc_ntfy_scan_start(rtwdev, rtwvif_link->phy_idx, chan->band_type); + rtw89_chip_rfk_scan(rtwdev, rtwvif_link, true); rtw89_hci_recalc_int_mit(rtwdev); rtw89_phy_config_edcca(rtwdev, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, mac_addr); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr); } void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, bool hw_scan) + struct rtw89_vif_link *rtwvif_link, bool hw_scan) { - struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; + struct ieee80211_bss_conf *bss_conf; - if (!rtwvif) + if (!rtwvif_link) return; - ether_addr_copy(rtwvif->mac_addr, vif->addr); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); + + rcu_read_unlock(); + + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); - rtw89_chip_rfk_scan(rtwdev, rtwvif, false); - rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0); + rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); + rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx); rtw89_phy_config_edcca(rtwdev, false); rtwdev->scanning = false; @@ -4688,17 +4993,39 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_chip_info_setup); +void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->he_support || !vif->cfg.assoc) { + rcu_read_unlock(); + return; + } + + rcu_read_unlock(); + + if (chip->ops->set_txpwr_ul_tb_offset) + chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx); +} + static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; + u8 n = rtwdev->support_mlo ? chip->support_link_num : 1; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; int ret; int tx_headroom = IEEE80211_HT_CTL_LEN; - hw->vif_data_size = sizeof(struct rtw89_vif); - hw->sta_data_size = sizeof(struct rtw89_sta); + hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n); + hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n); hw->txq_data_size = sizeof(struct rtw89_txq); hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 4ed9034fdb46..38df161bfd35 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -829,6 +829,8 @@ enum rtw89_phy_idx { RTW89_PHY_MAX }; +#define __RTW89_MLD_MAX_LINK_NUM 2 + enum rtw89_chanctx_idx { RTW89_CHANCTX_0 = 0, RTW89_CHANCTX_1 = 1, @@ -1166,8 +1168,8 @@ struct rtw89_core_tx_request { enum rtw89_core_tx_type tx_type; struct sk_buff *skb; - struct ieee80211_vif *vif; - struct ieee80211_sta *sta; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_tx_desc_info desc_info; }; @@ -1350,7 +1352,6 @@ struct rtw89_btc_wl_smap { u32 connecting: 1; u32 roaming: 1; u32 dbccing: 1; - u32 transacting: 1; u32 _4way: 1; u32 rf_off: 1; u32 lps: 2; @@ -2937,6 +2938,7 @@ struct rtw89_btc_dm { u8 wl_pre_agc: 2; u8 wl_lna2: 1; + u8 freerun_chk: 1; u8 wl_pre_agc_rb: 2; u8 bt_select: 2; /* 0:s0, 1:s1, 2:s0 & s1, refer to enum btc_bt_index */ u8 slot_req_more: 1; @@ -2975,6 +2977,8 @@ enum rtw89_btc_btf_fw_event { BTF_EVNT_BT_REG = 3, BTF_EVNT_CX_RUNINFO = 4, BTF_EVNT_BT_PSD = 5, + BTF_EVNT_BT_DEV_INFO = 6, /* fwc2hfunc > 0 */ + BTF_EVNT_BT_LEAUDIO_INFO = 7, /* fwc2hfunc > 1 */ BTF_EVNT_BUF_OVERFLOW, BTF_EVNT_C2H_LOOPBACK, BTF_EVNT_MAX, @@ -3141,6 +3145,7 @@ struct rtw89_btc_ver { u8 fcxinit; u8 fwevntrptl; + u8 fwc2hfunc; u8 drvinfo_type; u16 info_buf; u8 max_role_num; @@ -3354,12 +3359,13 @@ struct rtw89_sec_cam_entry { u8 key[32]; }; -struct rtw89_sta { +struct rtw89_sta_link { + struct rtw89_sta *rtwsta; + unsigned int link_id; + u8 mac_id; - bool disassoc; bool er_cap; - struct rtw89_dev *rtwdev; - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; struct rtw89_ra_info ra; struct rtw89_ra_report ra_report; int max_agg_wait; @@ -3370,15 +3376,12 @@ struct rtw89_sta { struct ewma_evm evm_1ss; struct ewma_evm evm_min[RF_PATH_MAX]; struct ewma_evm evm_max[RF_PATH_MAX]; - struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; - DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); struct ieee80211_rx_status rx_status; u16 rx_hw_rate; __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; - struct sk_buff_head roc_queue; bool use_cfg_mask; struct cfg80211_bitrate_mask mask; @@ -3460,10 +3463,10 @@ struct rtw89_p2p_noa_setter { u8 noa_index; }; -struct rtw89_vif { - struct list_head list; - struct rtw89_dev *rtwdev; - struct rtw89_roc roc; +struct rtw89_vif_link { + struct rtw89_vif *rtwvif; + unsigned int link_id; + bool chanctx_assigned; /* only valid when running with chanctx_ops */ enum rtw89_chanctx_idx chanctx_idx; enum rtw89_reg_6ghz_power reg_6ghz_power; @@ -3473,7 +3476,6 @@ struct rtw89_vif { u8 port; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; - __be32 ip_addr; u8 phy_idx; u8 mac_idx; u8 net_type; @@ -3484,7 +3486,6 @@ struct rtw89_vif { u8 hit_rule; u8 last_noa_nr; u64 sync_bcn_tsf; - bool offchan; bool trigger; bool lsig_txop; u8 tgt_ind; @@ -3498,15 +3499,11 @@ struct rtw89_vif { bool pre_pwr_diff_en; bool pwr_diff_en; u8 def_tri_idx; - u32 tdls_peer; struct work_struct update_beacon_work; struct rtw89_addr_cam_entry addr_cam; struct rtw89_bssid_cam_entry bssid_cam; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; - struct rtw89_traffic_stats stats; 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; struct rtw89_p2p_noa_setter p2p_noa; }; @@ -3599,11 +3596,11 @@ struct rtw89_chip_ops { void (*rfk_hw_init)(struct rtw89_dev *rtwdev); void (*rfk_init)(struct rtw89_dev *rtwdev); void (*rfk_init_late)(struct rtw89_dev *rtwdev); - void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void (*rfk_band_changed)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan); - void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool start); void (*rfk_track)(struct rtw89_dev *rtwdev); void (*power_trim)(struct rtw89_dev *rtwdev); @@ -3646,23 +3643,25 @@ struct rtw89_chip_ops { u32 *tx_en, enum rtw89_sch_tx_sel sel); int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); int (*h2c_dctl_sec_cam)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_default_cmac_tbl)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); - int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + 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, bool valid, struct ieee80211_ampdu_params *params); void (*btc_set_rfe)(struct rtw89_dev *rtwdev); @@ -4445,6 +4444,8 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0, RTW89_FW_FEATURE_WOW_REASON_V1, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, + RTW89_FW_FEATURE_RFK_RXDCK_V0, + RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, }; struct rtw89_fw_suit { @@ -4672,7 +4673,7 @@ struct rtw89_hal { struct rtw89_chanctx chanctx[NUM_OF_RTW89_CHANCTX]; struct cfg80211_chan_def roc_chandef; - bool entity_active; + bool entity_active[RTW89_PHY_MAX]; bool entity_pause; enum rtw89_entity_mode entity_mode; @@ -4750,6 +4751,7 @@ DECLARE_EWMA(thermal, 4, 4); struct rtw89_phy_stat { struct ewma_thermal avg_thermal[RF_PATH_MAX]; + struct ewma_rssi bcn_rssi; struct rtw89_pkt_stat cur_pkt_stat; struct rtw89_pkt_stat last_pkt_stat; }; @@ -5196,7 +5198,7 @@ struct rtw89_early_h2c { }; struct rtw89_hw_scan_info { - struct ieee80211_vif *scanning_vif; + struct rtw89_vif_link *scanning_vif; struct list_head pkt_list[NUM_NL80211_BANDS]; struct rtw89_chan op_chan; bool abort; @@ -5371,7 +5373,7 @@ struct rtw89_wow_aoac_report { }; struct rtw89_wow_param { - struct ieee80211_vif *wow_vif; + struct rtw89_vif_link *rtwvif_link; DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM); struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM]; struct rtw89_wow_key_info key_info; @@ -5408,7 +5410,7 @@ struct rtw89_mcc_policy { }; struct rtw89_mcc_role { - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; struct rtw89_mcc_policy policy; struct rtw89_mcc_limit limit; @@ -5608,6 +5610,121 @@ struct rtw89_dev { u8 priv[] __aligned(sizeof(void *)); }; +struct rtw89_vif { + struct rtw89_dev *rtwdev; + struct list_head list; + + u8 mac_addr[ETH_ALEN]; + __be32 ip_addr; + + struct rtw89_traffic_stats stats; + u32 tdls_peer; + + struct ieee80211_scan_ies *scan_ies; + struct cfg80211_scan_request *scan_req; + + struct rtw89_roc roc; + bool offchan; + + u8 links_inst_valid_num; + DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; + struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num); +}; + +static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif_link, + const struct rtw89_vif *rtwvif, + unsigned int link_id) +{ + *rtwvif_link = rtwvif->links[link_id]; + return !!*rtwvif_link; +} + +#define rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) \ + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ + if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id)) + +struct rtw89_sta { + struct rtw89_dev *rtwdev; + struct rtw89_vif *rtwvif; + + bool disassoc; + + struct sk_buff_head roc_queue; + + struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; + DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); + + u8 links_inst_valid_num; + DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; + struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num); +}; + +static inline bool rtw89_sta_assign_link_is_valid(struct rtw89_sta_link **rtwsta_link, + const struct rtw89_sta *rtwsta, + unsigned int link_id) +{ + *rtwsta_link = rtwsta->links[link_id]; + return !!*rtwsta_link; +} + +#define rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) \ + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ + if (rtw89_sta_assign_link_is_valid(&(rtwsta_link), rtwsta, link_id)) + +static inline u8 rtw89_vif_get_main_macid(struct rtw89_vif *rtwvif) +{ + /* const after init, so no need to check if active first */ + return rtwvif->links_inst[0].mac_id; +} + +static inline u8 rtw89_vif_get_main_port(struct rtw89_vif *rtwvif) +{ + /* const after init, so no need to check if active first */ + return rtwvif->links_inst[0].port; +} + +static inline struct rtw89_vif_link * +rtw89_vif_get_link_inst(struct rtw89_vif *rtwvif, u8 index) +{ + if (index >= rtwvif->links_inst_valid_num || + !test_bit(index, rtwvif->links_inst_map)) + return NULL; + return &rtwvif->links_inst[index]; +} + +static inline +u8 rtw89_vif_link_inst_get_index(struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + + return rtwvif_link - rtwvif->links_inst; +} + +static inline u8 rtw89_sta_get_main_macid(struct rtw89_sta *rtwsta) +{ + /* const after init, so no need to check if active first */ + return rtwsta->links_inst[0].mac_id; +} + +static inline struct rtw89_sta_link * +rtw89_sta_get_link_inst(struct rtw89_sta *rtwsta, u8 index) +{ + if (index >= rtwsta->links_inst_valid_num || + !test_bit(index, rtwsta->links_inst_map)) + return NULL; + return &rtwsta->links_inst[index]; +} + +static inline +u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + + return rtwsta_link - rtwsta->links_inst; +} + static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { @@ -5972,9 +6089,26 @@ static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif) return rtwvif ? rtwvif_to_vif(rtwvif) : NULL; } +static inline +struct ieee80211_vif *rtwvif_link_to_vif(struct rtw89_vif_link *rtwvif_link) +{ + return rtwvif_to_vif(rtwvif_link->rtwvif); +} + +static inline +struct ieee80211_vif *rtwvif_link_to_vif_safe(struct rtw89_vif_link *rtwvif_link) +{ + return rtwvif_link ? rtwvif_link_to_vif(rtwvif_link) : NULL; +} + +static inline struct rtw89_vif *vif_to_rtwvif(struct ieee80211_vif *vif) +{ + return (struct rtw89_vif *)vif->drv_priv; +} + static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif) { - return vif ? (struct rtw89_vif *)vif->drv_priv : NULL; + return vif ? vif_to_rtwvif(vif) : NULL; } static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta) @@ -5989,11 +6123,88 @@ static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta) return rtwsta ? rtwsta_to_sta(rtwsta) : NULL; } +static inline +struct ieee80211_sta *rtwsta_link_to_sta(struct rtw89_sta_link *rtwsta_link) +{ + return rtwsta_to_sta(rtwsta_link->rtwsta); +} + +static inline +struct ieee80211_sta *rtwsta_link_to_sta_safe(struct rtw89_sta_link *rtwsta_link) +{ + return rtwsta_link ? rtwsta_link_to_sta(rtwsta_link) : NULL; +} + +static inline struct rtw89_sta *sta_to_rtwsta(struct ieee80211_sta *sta) +{ + return (struct rtw89_sta *)sta->drv_priv; +} + static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta) { - return sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + return sta ? sta_to_rtwsta(sta) : NULL; +} + +static inline struct ieee80211_bss_conf * +__rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink) +{ + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + + bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]); + if (unlikely(!bss_conf)) { + *nolink = true; + return &vif->bss_conf; + } + + *nolink = false; + return bss_conf; } +#define rtw89_vif_rcu_dereference_link(rtwvif_link, assert) \ +({ \ + typeof(rtwvif_link) p = rtwvif_link; \ + struct ieee80211_bss_conf *bss_conf; \ + bool nolink; \ + \ + bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ + rtw89_err(p->rtwvif->rtwdev, \ + "%s: cannot find exact bss_conf for link_id %u\n",\ + __func__, p->link_id); \ + bss_conf; \ +}) + +static inline struct ieee80211_link_sta * +__rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink) +{ + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct ieee80211_link_sta *link_sta; + + link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]); + if (unlikely(!link_sta)) { + *nolink = true; + return &sta->deflink; + } + + *nolink = false; + return link_sta; +} + +#define rtw89_sta_rcu_dereference_link(rtwsta_link, assert) \ +({ \ + typeof(rtwsta_link) p = rtwsta_link; \ + struct ieee80211_link_sta *link_sta; \ + bool nolink; \ + \ + link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ + rtw89_err(p->rtwsta->rtwdev, \ + "%s: cannot find exact link_sta for link_id %u\n",\ + __func__, p->link_id); \ + link_sta; \ +}) + static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) { if (hw_bw == RTW89_CHANNEL_WIDTH_160) @@ -6078,29 +6289,29 @@ enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua) } static inline -struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - if (rtwsta) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + if (rtwsta_link) { + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) - return &rtwsta->addr_cam; + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + return &rtwsta_link->addr_cam; } - return &rtwvif->addr_cam; + return &rtwvif_link->addr_cam; } static inline -struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - if (rtwsta) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + if (rtwsta_link) { + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); if (sta->tdls) - return &rtwsta->bssid_cam; + return &rtwsta_link->bssid_cam; } - return &rtwvif->bssid_cam; + return &rtwvif_link->bssid_cam; } static inline @@ -6159,11 +6370,10 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev, static inline const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; - if (rtwvif) - return rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + if (rtwvif_link) + return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); else return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); } @@ -6240,12 +6450,12 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev) } static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->rfk_channel) - chip->ops->rfk_channel(rtwdev, rtwvif); + chip->ops->rfk_channel(rtwdev, rtwvif_link); } static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, @@ -6259,12 +6469,12 @@ static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, } static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool start) + struct rtw89_vif_link *rtwvif_link, bool start) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->rfk_scan) - chip->ops->rfk_scan(rtwdev, rtwvif, start); + chip->ops->rfk_scan(rtwdev, rtwvif_link, start); } static inline void rtw89_chip_rfk_track(struct rtw89_dev *rtwdev) @@ -6279,8 +6489,12 @@ static inline void rtw89_chip_set_txpwr_ctrl(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - if (chip->ops->set_txpwr_ctrl) - chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0); + if (!chip->ops->set_txpwr_ctrl) + return; + + chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_1); } static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev) @@ -6291,8 +6505,8 @@ static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev) chip->ops->power_trim(rtwdev); } -static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) +static inline void __rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -6300,6 +6514,13 @@ static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, chip->ops->init_txpwr_unit(rtwdev, phy_idx); } +static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev) +{ + __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_1); +} + static inline u8 rtw89_chip_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { @@ -6347,20 +6568,6 @@ static inline void rtw89_chip_cfg_txrx_path(struct rtw89_dev *rtwdev) chip->ops->cfg_txrx_path(rtwdev); } -static inline -void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) -{ - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - const struct rtw89_chip_info *chip = rtwdev->chip; - - if (!vif->bss_conf.he_support || !vif->cfg.assoc) - return; - - if (chip->ops->set_txpwr_ul_tb_offset) - chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif->mac_idx); -} - static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -6457,14 +6664,14 @@ int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en) static inline int rtw89_chip_h2c_dctl_sec_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (!chip->ops->h2c_dctl_sec_cam) return 0; - return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); } static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) @@ -6479,13 +6686,14 @@ static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) return hdr->addr3; } -static inline bool rtw89_sta_has_beamformer_cap(struct ieee80211_sta *sta) +static inline +bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta) { - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || - (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || + (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || - (sta->deflink.he_cap.he_cap_elem.phy_cap_info[4] & + (link_sta->he_cap.he_cap_elem.phy_cap_info[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) return true; return false; @@ -6605,21 +6813,21 @@ void rtw89_core_napi_start(struct rtw89_dev *rtwdev); void rtw89_core_napi_stop(struct rtw89_dev *rtwdev); int rtw89_core_napi_init(struct rtw89_dev *rtwdev); void rtw89_core_napi_deinit(struct rtw89_dev *rtwdev); -int rtw89_core_sta_add(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, struct cfg80211_tid_config *tid_config); @@ -6635,22 +6843,40 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev); u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev); void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id); +void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + u8 mac_id, u8 port); +void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta, u8 mac_id); +struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, + unsigned int link_id); +void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id); +struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, + unsigned int link_id); +void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, struct rtw89_chan *chan); int rtw89_set_channel(struct rtw89_dev *rtwdev); -void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_chan *chan); 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 *rtwsta, u8 tid, u8 *cam_idx); + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); -void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); +void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc); int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); +void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); int rtw89_regd_setup(struct rtw89_dev *rtwdev); int rtw89_regd_init(struct rtw89_dev *rtwdev, @@ -6667,13 +6893,15 @@ void rtw89_core_update_beacon_work(struct work_struct *work); void rtw89_roc_work(struct work_struct *work); void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); -void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, const u8 *mac_addr, bool hw_scan); void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, bool hw_scan); -int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool hw_scan); +int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool active); -void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf); void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event); #endif diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 29f85210f919..74b0c722a5b8 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3506,7 +3506,9 @@ out: return count; } -static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) +static void rtw89_sta_link_info_get_iter(struct seq_file *m, + struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { static const char * const he_gi_str[] = { [NL80211_RATE_INFO_HE_GI_0_8] = "0.8", @@ -3518,20 +3520,26 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) [NL80211_RATE_INFO_EHT_GI_1_6] = "1.6", [NL80211_RATE_INFO_EHT_GI_3_2] = "3.2", }; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rate_info *rate = &rtwsta->ra_report.txrate; - struct ieee80211_rx_status *status = &rtwsta->rx_status; - struct seq_file *m = (struct seq_file *)data; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rate_info *rate = &rtwsta_link->ra_report.txrate; + struct ieee80211_rx_status *status = &rtwsta_link->rx_status; struct rtw89_hal *hal = &rtwdev->hal; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; + struct ieee80211_link_sta *link_sta; u8 evm_min, evm_max, evm_1ss; + u16 max_rc_amsdu_len; u8 rssi; u8 snr; int i; - seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id); + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + max_rc_amsdu_len = link_sta->agg.max_rc_amsdu_len; + + rcu_read_unlock(); + + seq_printf(m, "TX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); if (rate->flags & RATE_INFO_FLAGS_MCS) seq_printf(m, "HT MCS-%d%s", rate->mcs, @@ -3549,13 +3557,13 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) eht_gi_str[rate->eht_gi] : "N/A"); else seq_printf(m, "Legacy %d", rate->legacy); - seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : ""); + seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : ""); seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); - seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate); - seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait, - sta->deflink.agg.max_rc_amsdu_len); + seq_printf(m, " (hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); + seq_printf(m, " ==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, + max_rc_amsdu_len); - seq_printf(m, "RX rate [%d]: ", rtwsta->mac_id); + seq_printf(m, "RX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); switch (status->encoding) { case RX_ENC_LEGACY: @@ -3582,24 +3590,24 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) break; } seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); - seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate); + seq_printf(m, " (hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate); - rssi = ewma_rssi_read(&rtwsta->avg_rssi); + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [", - RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi); + RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta_link->prev_rssi); for (i = 0; i < ant_num; i++) { - rssi = ewma_rssi_read(&rtwsta->rssi[i]); + rssi = ewma_rssi_read(&rtwsta_link->rssi[i]); seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi), ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "", i + 1 == ant_num ? "" : ", "); } seq_puts(m, "]\n"); - evm_1ss = ewma_evm_read(&rtwsta->evm_1ss); + evm_1ss = ewma_evm_read(&rtwsta_link->evm_1ss); seq_printf(m, "EVM: [%2u.%02u, ", evm_1ss >> 2, (evm_1ss & 0x3) * 25); for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) { - evm_min = ewma_evm_read(&rtwsta->evm_min[i]); - evm_max = ewma_evm_read(&rtwsta->evm_max[i]); + evm_min = ewma_evm_read(&rtwsta_link->evm_min[i]); + evm_max = ewma_evm_read(&rtwsta_link->evm_max[i]); seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ", evm_min >> 2, (evm_min & 0x3) * 25, @@ -3607,10 +3615,22 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) } seq_puts(m, "]\t"); - snr = ewma_snr_read(&rtwsta->avg_snr); + snr = ewma_snr_read(&rtwsta_link->avg_snr); seq_printf(m, "SNR: %u\n", snr); } +static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) +{ + struct seq_file *m = (struct seq_file *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + rtw89_sta_link_info_get_iter(m, rtwdev, rtwsta_link); +} + static void rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat, enum rtw89_hw_rate first_rate, int len) @@ -3653,13 +3673,16 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_rx_rate_cnt_info *info; enum rtw89_hw_rate first_rate; + u8 rssi; int i; + rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi); + seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n", stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv, stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv); - seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr, - stats->rx_tf_periodic); + seq_printf(m, "Beacon: %u (%d dBm), TF: %u\n", pkt_stat->beacon_nr, + RTW89_RSSI_RAW_TO_DBM(rssi), stats->rx_tf_periodic); seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len, stats->rx_avg_len); @@ -3737,28 +3760,41 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis seq_puts(m, "\n"); } +static void rtw89_vif_link_ids_get(struct seq_file *m, u8 *mac, + struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + + seq_printf(m, " [%u] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr); + seq_printf(m, "\tlink_id=%u\n", rtwvif_link->link_id); + seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); + rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam); + rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list, + "\tpkt_ofld[GENERAL]: "); +} + static void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; struct seq_file *m = (struct seq_file *)data; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr); - seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); - rtw89_dump_addr_cam(m, rtwdev, &rtwvif->addr_cam); - rtw89_dump_pkt_offload(m, &rtwvif->general_pkt_list, "\tpkt_ofld[GENERAL]: "); + seq_printf(m, "VIF %pM\n", rtwvif->mac_addr); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_vif_link_ids_get(m, mac, rtwdev, rtwvif_link); } -static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) +static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; struct rtw89_ba_cam_entry *entry; bool first = true; - list_for_each_entry(entry, &rtwsta->ba_cam_list, list) { + list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) { if (first) { seq_puts(m, "\tba_cam "); first = false; @@ -3771,16 +3807,36 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) seq_puts(m, "\n"); } +static void rtw89_sta_link_ids_get(struct seq_file *m, + struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) +{ + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + seq_printf(m, " [%u] %pM\n", rtwsta_link->mac_id, link_sta->addr); + + rcu_read_unlock(); + + seq_printf(m, "\tlink_id=%u\n", rtwsta_link->link_id); + rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam); + rtw89_dump_ba_cam(m, rtwdev, rtwsta_link); +} + static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; struct seq_file *m = (struct seq_file *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; - seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr, - sta->tdls ? "(TDLS)" : ""); - rtw89_dump_addr_cam(m, rtwdev, &rtwsta->addr_cam); - rtw89_dump_ba_cam(m, rtwsta); + seq_printf(m, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : ""); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + rtw89_sta_link_ids_get(m, rtwdev, rtwsta_link); } static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d9b0e7ebe619..2c2fdf21f065 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -665,11 +665,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 37, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD), + __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER), @@ -687,6 +689,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, @@ -1741,8 +1744,8 @@ plain_log: } #define H2C_CAM_LEN 60 -int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, const u8 *scan_mac_addr) +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 sk_buff *skb; int ret; @@ -1753,8 +1756,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, return -ENOMEM; } skb_put(skb, H2C_CAM_LEN); - rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif, rtwsta, scan_mac_addr, skb->data); - rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif, rtwsta, skb->data); + rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr, + skb->data); + rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1776,8 +1780,8 @@ fail: } int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { struct rtw89_h2c_dctlinfo_ud_v1 *h2c; u32 len = sizeof(*h2c); @@ -1792,7 +1796,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_dctlinfo_ud_v1 *)skb->data; - rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif, rtwsta, h2c); + rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta_link, h2c); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1815,8 +1819,8 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1); int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { struct rtw89_h2c_dctlinfo_ud_v2 *h2c; u32 len = sizeof(*h2c); @@ -1831,7 +1835,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data; - rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif, rtwsta, h2c); + rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta_link, h2c); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1854,10 +1858,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_dctlinfo_ud_v2 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -1908,21 +1912,24 @@ fail: } EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); -int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_h2c_ba_cam *h2c; - u8 macid = rtwsta->mac_id; + u8 macid = rtwsta_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; int ret; ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx) : + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because * hardware can create dynamic BA CAM automatically. @@ -1960,7 +1967,8 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, if (chip->bacam_ver == RTW89_BACAM_V0_EXT) { h2c->w1 |= le32_encode_bits(1, RTW89_H2C_BA_CAM_W1_STD_EN) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BA_CAM_W1_BAND); + le32_encode_bits(rtwvif_link->mac_idx, + RTW89_H2C_BA_CAM_W1_BAND); } end: @@ -2039,13 +2047,14 @@ 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_sta *rtwsta, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_h2c_ba_cam_v1 *h2c; - u8 macid = rtwsta->mac_id; + u8 macid = rtwsta_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; @@ -2053,8 +2062,10 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, int ret; ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx) : + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because * hardware can create dynamic BA CAM automatically. @@ -2092,7 +2103,8 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, 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(!!rtwvif->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); + le32_encode_bits(!!rtwvif_link->mac_idx, + RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -2197,15 +2209,14 @@ fail: } static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { static const u8 gtkbody[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_eapol_2_of_2 *eapol_pkt; + struct ieee80211_bss_conf *bss_conf; struct ieee80211_hdr_3addr *hdr; struct sk_buff *skb; u8 key_des_ver; @@ -2227,10 +2238,17 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS | IEEE80211_FCTL_PROTECTED); + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(hdr->addr1, bss_conf->bssid); - ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); ether_addr_copy(hdr->addr3, bss_conf->bssid); + rcu_read_unlock(); + skb_put_zero(skb, sec_hdr_len); eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt)); @@ -2241,11 +2259,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, } static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct ieee80211_bss_conf *bss_conf; struct ieee80211_hdr_3addr *hdr; struct rtw89_sa_query *sa_query; struct sk_buff *skb; @@ -2258,10 +2275,17 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION | IEEE80211_FCTL_PROTECTED); + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(hdr->addr1, bss_conf->bssid); - ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); ether_addr_copy(hdr->addr3, bss_conf->bssid); + rcu_read_unlock(); + skb_put_zero(skb, sec_hdr_len); sa_query = skb_put_zero(skb, sizeof(*sa_query)); @@ -2272,8 +2296,9 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, } static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct ieee80211_hdr_3addr *hdr; @@ -2295,9 +2320,9 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); hdr->frame_control = fc; - ether_addr_copy(hdr->addr1, rtwvif->bssid); - ether_addr_copy(hdr->addr2, rtwvif->mac_addr); - ether_addr_copy(hdr->addr3, rtwvif->bssid); + ether_addr_copy(hdr->addr1, rtwvif_link->bssid); + ether_addr_copy(hdr->addr2, rtwvif_link->mac_addr); + ether_addr_copy(hdr->addr3, rtwvif_link->bssid); skb_put_zero(skb, sec_hdr_len); @@ -2312,18 +2337,18 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(ARPOP_REPLY); - ether_addr_copy(arp_skb->sender_hw, rtwvif->mac_addr); + ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr); arp_skb->sender_ip = rtwvif->ip_addr; return skb; } static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, enum rtw89_fw_pkt_ofld_type type, u8 *id) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_pktofld_info *info; struct sk_buff *skb; int ret; @@ -2346,13 +2371,13 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); break; case RTW89_PKT_OFLD_TYPE_EAPOL_KEY: - skb = rtw89_eapol_get(rtwdev, rtwvif); + skb = rtw89_eapol_get(rtwdev, rtwvif_link); break; case RTW89_PKT_OFLD_TYPE_SA_QUERY: - skb = rtw89_sa_query_get(rtwdev, rtwvif); + skb = rtw89_sa_query_get(rtwdev, rtwvif_link); break; case RTW89_PKT_OFLD_TYPE_ARP_RSP: - skb = rtw89_arp_response_get(rtwdev, rtwvif); + skb = rtw89_arp_response_get(rtwdev, rtwvif_link); break; default: goto err; @@ -2367,7 +2392,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, if (ret) goto err; - list_add_tail(&info->list, &rtwvif->general_pkt_list); + list_add_tail(&info->list, &rtwvif_link->general_pkt_list); *id = info->id; return 0; @@ -2377,9 +2402,10 @@ err: } void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool notify_fw) + struct rtw89_vif_link *rtwvif_link, + bool notify_fw) { - struct list_head *pkt_list = &rtwvif->general_pkt_list; + struct list_head *pkt_list = &rtwvif_link->general_pkt_list; struct rtw89_pktofld_info *info, *tmp; list_for_each_entry_safe(info, tmp, pkt_list, list) { @@ -2394,16 +2420,20 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, + 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, - struct rtw89_vif *rtwvif, u8 macid) + struct rtw89_vif_link *rtwvif_link, u8 macid) { u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND; u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND; @@ -2411,11 +2441,11 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct sk_buff *skb; int ret; - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_PS_POLL, &pkt_id_ps_poll); - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id_null); - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_QOS_NULL, &pkt_id_qos_null); skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN); @@ -2494,10 +2524,10 @@ fail: return ret; } -int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_h2c_lps_ch_info *h2c; u32 len = sizeof(*h2c); @@ -2546,13 +2576,14 @@ fail: } #define H2C_P2P_ACT_LEN 20 -int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct ieee80211_p2p_noa_desc *desc, u8 act, u8 noa_id) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; - u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow; + bool p2p_type_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + u8 ctwindow_oppps = bss_conf->p2p_noa_attr.oppps_ctwindow; struct sk_buff *skb; u8 *cmd; int ret; @@ -2565,7 +2596,7 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, skb_put(skb, H2C_P2P_ACT_LEN); cmd = skb->data; - RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif->mac_id); + RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif_link->mac_id); RTW89_SET_FWCMD_P2P_P2PID(cmd, 0); RTW89_SET_FWCMD_P2P_NOAID(cmd, noa_id); RTW89_SET_FWCMD_P2P_ACT(cmd, act); @@ -2622,11 +2653,11 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev, #define H2C_CMC_TBL_LEN 68 int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - u8 macid = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 macid = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct sk_buff *skb; int ret; @@ -2648,7 +2679,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, } SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0); SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) SET_CMC_TBL_DATA_DCM(skb->data, 0); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -2671,10 +2702,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl); int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -2755,24 +2786,25 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7); static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, u8 *pads) + struct ieee80211_link_sta *link_sta, + u8 *pads) { bool ppe_th; u8 ppe16, ppe8; - u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; - u8 ppe_thres_hdr = sta->deflink.he_cap.ppe_thres[0]; + u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; + u8 ppe_thres_hdr = link_sta->he_cap.ppe_thres[0]; u8 ru_bitmap; u8 n, idx, sh; u16 ppe; int i; ppe_th = FIELD_GET(IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT, - sta->deflink.he_cap.he_cap_elem.phy_cap_info[6]); + link_sta->he_cap.he_cap_elem.phy_cap_info[6]); if (!ppe_th) { u8 pad; pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK, - sta->deflink.he_cap.he_cap_elem.phy_cap_info[9]); + link_sta->he_cap.he_cap_elem.phy_cap_info[9]); for (i = 0; i < RTW89_PPE_BW_NUM; i++) pads[i] = pad; @@ -2794,7 +2826,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, sh = n & 7; n += IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2; - ppe = le16_to_cpu(*((__le16 *)&sta->deflink.he_cap.ppe_thres[idx])); + ppe = le16_to_cpu(*((__le16 *)&link_sta->he_cap.ppe_thres[idx])); ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; sh += IEEE80211_PPE_THRES_INFO_PPET_SIZE; ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; @@ -2809,23 +2841,35 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, } int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); + struct ieee80211_link_sta *link_sta; struct sk_buff *skb; u8 pads[RTW89_PPE_BW_NUM]; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; u16 lowest_rate; int ret; memset(pads, 0, sizeof(pads)); - if (sta && sta->deflink.he_cap.has_he) - __get_sta_he_pkt_padding(rtwdev, sta, pads); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); + return -ENOMEM; + } + + rcu_read_lock(); + + if (rtwsta_link) + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (rtwsta_link && link_sta->he_cap.has_he) + __get_sta_he_pkt_padding(rtwdev, link_sta, pads); if (vif->p2p) lowest_rate = RTW89_HW_RATE_OFDM6; @@ -2834,11 +2878,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); - if (!skb) { - rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); - return -ENOMEM; - } skb_put(skb, H2C_CMC_TBL_LEN); SET_CTRL_INFO_MACID(skb->data, mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); @@ -2851,7 +2890,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, SET_CMC_TBL_ULDL(skb->data, 1); else SET_CMC_TBL_ULDL(skb->data, 0); - SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif->port); + SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif_link->port); if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD_V1) { SET_CMC_TBL_NOMINAL_PKT_PADDING_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_20]); SET_CMC_TBL_NOMINAL_PKT_PADDING40_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_40]); @@ -2863,12 +2902,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, SET_CMC_TBL_NOMINAL_PKT_PADDING80(skb->data, pads[RTW89_CHANNEL_WIDTH_80]); SET_CMC_TBL_NOMINAL_PKT_PADDING160(skb->data, pads[RTW89_CHANNEL_WIDTH_160]); } - if (sta) + if (rtwsta_link) SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, - sta->deflink.he_cap.has_he); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + link_sta->he_cap.has_he); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) SET_CMC_TBL_DATA_DCM(skb->data, 0); + rcu_read_unlock(); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, chip->h2c_cctl_func_id, 0, 1, @@ -2889,9 +2930,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl); static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, u8 *pads) + struct ieee80211_link_sta *link_sta, + u8 *pads) { - u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; + u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; u16 ppe_thres_hdr; u8 ppe16, ppe8; u8 n, idx, sh; @@ -2900,12 +2942,12 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, u16 ppe; int i; - ppe_th = !!u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], + ppe_th = !!u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT); if (!ppe_th) { u8 pad; - pad = u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], + pad = u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK); for (i = 0; i < RTW89_PPE_BW_NUM; i++) @@ -2914,7 +2956,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, return; } - ppe_thres_hdr = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres); + ppe_thres_hdr = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres); ru_bitmap = u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); n = hweight8(ru_bitmap); @@ -2931,7 +2973,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, sh = n & 7; n += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2; - ppe = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres + idx); + ppe = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres + idx); ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; sh += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE; ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; @@ -2946,14 +2988,15 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, } int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; u8 pads[RTW89_PPE_BW_NUM]; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -2961,11 +3004,24 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, int ret; memset(pads, 0, sizeof(pads)); - if (sta) { - if (sta->deflink.eht_cap.has_eht) - __get_sta_eht_pkt_padding(rtwdev, sta, pads); - else if (sta->deflink.he_cap.has_he) - __get_sta_he_pkt_padding(rtwdev, sta, pads); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); + return -ENOMEM; + } + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->eht_cap.has_eht) + __get_sta_eht_pkt_padding(rtwdev, link_sta, pads); + else if (link_sta->he_cap.has_he) + __get_sta_he_pkt_padding(rtwdev, link_sta, pads); } if (vif->p2p) @@ -2975,11 +3031,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); - if (!skb) { - rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); - return -ENOMEM; - } skb_put(skb, len); h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; @@ -3000,16 +3051,16 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, h2c->w3 = le32_encode_bits(0, CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); - h2c->w4 = le32_encode_bits(rtwvif->port, CCTLINFO_G7_W4_MULTI_PORT_ID); + h2c->w4 = le32_encode_bits(rtwvif_link->port, CCTLINFO_G7_W4_MULTI_PORT_ID); h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_MULTI_PORT_ID); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { h2c->w4 |= le32_encode_bits(0, CCTLINFO_G7_W4_DATA_DCM); h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM); } - if (vif->bss_conf.eht_support) { - u16 punct = vif->bss_conf.chanreq.oper.punctured; + if (bss_conf->eht_support) { + u16 punct = bss_conf->chanreq.oper.punctured; h2c->w4 |= le32_encode_bits(~punct, CCTLINFO_G7_W4_ACT_SUBCH_CBW); @@ -3036,12 +3087,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, CCTLINFO_G7_W6_ULDL); h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); - if (sta) { - h2c->w8 = le32_encode_bits(sta->deflink.he_cap.has_he, + if (rtwsta_link) { + h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); } + rcu_read_unlock(); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, @@ -3062,10 +3115,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7); int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -3102,7 +3155,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, else if (agg_num > 0x200 && agg_num <= 0x400) ba_bmap = 5; - h2c->c0 = le32_encode_bits(rtwsta->mac_id, CCTLINFO_G7_C0_MACID) | + h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, CCTLINFO_G7_C0_MACID) | le32_encode_bits(1, CCTLINFO_G7_C0_OP); h2c->w3 = le32_encode_bits(ba_bmap, CCTLINFO_G7_W3_BA_BMAP); @@ -3128,7 +3181,7 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7); int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta) + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; struct sk_buff *skb; @@ -3140,15 +3193,15 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, return -ENOMEM; } skb_put(skb, H2C_CMC_TBL_LEN); - SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); + SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); - if (rtwsta->cctl_tx_time) { + if (rtwsta_link->cctl_tx_time) { SET_CMC_TBL_AMPDU_TIME_SEL(skb->data, 1); - SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta->ampdu_max_time); + SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta_link->ampdu_max_time); } - if (rtwsta->cctl_tx_retry_limit) { + if (rtwsta_link->cctl_tx_retry_limit) { SET_CMC_TBL_DATA_TXCNT_LMT_SEL(skb->data, 1); - SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta->data_tx_cnt_lmt); + SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta_link->data_tx_cnt_lmt); } rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -3170,7 +3223,7 @@ fail: } int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta) + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; struct sk_buff *skb; @@ -3185,7 +3238,7 @@ int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, return -ENOMEM; } skb_put(skb, H2C_CMC_TBL_LEN); - SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); + SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); __rtw89_fw_h2c_set_tx_path(rtwdev, skb); @@ -3209,11 +3262,11 @@ fail: } int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_h2c_bcn_upd *h2c; struct sk_buff *skb_beacon; struct ieee80211_hdr *hdr; @@ -3240,7 +3293,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, return -ENOMEM; } - noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); + noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); if (noa_len && (noa_len <= skb_tailroom(skb_beacon) || pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { @@ -3260,11 +3313,11 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcn_upd *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_W0_PORT) | + h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_W0_PORT) | le32_encode_bits(0, RTW89_H2C_BCN_UPD_W0_MBSSID) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_W0_GRP_IE_OFST); - h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | + h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_W1_SSN_SEL) | le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_W1_SSN_MODE) | le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_W1_RATE); @@ -3289,10 +3342,10 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon); int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_h2c_bcn_upd_be *h2c; struct sk_buff *skb_beacon; struct ieee80211_hdr *hdr; @@ -3319,7 +3372,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, return -ENOMEM; } - noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); + noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); if (noa_len && (noa_len <= skb_tailroom(skb_beacon) || pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { @@ -3339,11 +3392,11 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcn_upd_be *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | + h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | le32_encode_bits(0, RTW89_H2C_BCN_UPD_BE_W0_MBSSID) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_BE_W0_GRP_IE_OFST); - h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | + h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_BE_W1_SSN_SEL) | le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_BE_W1_SSN_MODE) | le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_BE_W1_RATE); @@ -3373,22 +3426,22 @@ EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); #define H2C_ROLE_MAINTAIN_LEN 4 int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, enum rtw89_upd_mode upd_mode) { struct sk_buff *skb; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; u8 self_role; int ret; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { - if (rtwsta) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { + if (rtwsta_link) self_role = RTW89_SELF_ROLE_AP_CLIENT; else - self_role = rtwvif->self_role; + self_role = rtwvif_link->self_role; } else { - self_role = rtwvif->self_role; + self_role = rtwvif_link->self_role; } skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN); @@ -3400,7 +3453,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id); SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role); SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode); - SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif->wifi_role); + SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif_link->wifi_role); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT, @@ -3421,39 +3474,53 @@ fail: } static enum rtw89_fw_sta_type -rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; + enum rtw89_fw_sta_type type; + + rcu_read_lock(); - if (!sta) + if (!rtwsta_link) goto by_vif; - if (sta->deflink.eht_cap.has_eht) - return RTW89_FW_BE_STA; - else if (sta->deflink.he_cap.has_he) - return RTW89_FW_AX_STA; + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->eht_cap.has_eht) + type = RTW89_FW_BE_STA; + else if (link_sta->he_cap.has_he) + type = RTW89_FW_AX_STA; else - return RTW89_FW_N_AC_STA; + type = RTW89_FW_N_AC_STA; + + goto out; by_vif: - if (vif->bss_conf.eht_support) - return RTW89_FW_BE_STA; - else if (vif->bss_conf.he_support) - return RTW89_FW_AX_STA; + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (bss_conf->eht_support) + type = RTW89_FW_BE_STA; + else if (bss_conf->he_support) + type = RTW89_FW_AX_STA; else - return RTW89_FW_N_AC_STA; + type = RTW89_FW_N_AC_STA; + +out: + rcu_read_unlock(); + + return type; } -int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, bool dis_conn) +int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool dis_conn) { struct sk_buff *skb; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; - u8 self_role = rtwvif->self_role; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + u8 self_role = rtwvif_link->self_role; enum rtw89_fw_sta_type sta_type; - u8 net_type = rtwvif->net_type; + u8 net_type = rtwvif_link->net_type; struct rtw89_h2c_join_v1 *h2c_v1; struct rtw89_h2c_join *h2c; u32 len = sizeof(*h2c); @@ -3465,7 +3532,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, format_v1 = true; } - if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) { + if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta_link) { self_role = RTW89_SELF_ROLE_AP_CLIENT; net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type; } @@ -3480,16 +3547,17 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_JOININFO_W0_MACID) | le32_encode_bits(dis_conn, RTW89_H2C_JOININFO_W0_OP) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | - le32_encode_bits(rtwvif->wmm, RTW89_H2C_JOININFO_W0_WMM) | - le32_encode_bits(rtwvif->trigger, RTW89_H2C_JOININFO_W0_TGR) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | + le32_encode_bits(rtwvif_link->wmm, RTW89_H2C_JOININFO_W0_WMM) | + le32_encode_bits(rtwvif_link->trigger, RTW89_H2C_JOININFO_W0_TGR) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_ISHESTA) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DLBW) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_TF_MAC_PAD) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DL_T_PE) | - le32_encode_bits(rtwvif->port, RTW89_H2C_JOININFO_W0_PORT_ID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_JOININFO_W0_PORT_ID) | le32_encode_bits(net_type, RTW89_H2C_JOININFO_W0_NET_TYPE) | - le32_encode_bits(rtwvif->wifi_role, RTW89_H2C_JOININFO_W0_WIFI_ROLE) | + le32_encode_bits(rtwvif_link->wifi_role, + RTW89_H2C_JOININFO_W0_WIFI_ROLE) | le32_encode_bits(self_role, RTW89_H2C_JOININFO_W0_SELF_ROLE); if (!format_v1) @@ -3497,7 +3565,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data; - sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif, rtwsta); + sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta_link); h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE); h2c_v1->w2 = 0; @@ -3618,7 +3686,7 @@ fail: } #define H2C_EDCA_LEN 12 -int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 ac, u32 val) { struct sk_buff *skb; @@ -3631,7 +3699,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, } skb_put(skb, H2C_EDCA_LEN); RTW89_SET_EDCA_SEL(skb->data, 0); - RTW89_SET_EDCA_BAND(skb->data, rtwvif->mac_idx); + RTW89_SET_EDCA_BAND(skb->data, rtwvif_link->mac_idx); RTW89_SET_EDCA_WMM(skb->data, 0); RTW89_SET_EDCA_AC(skb->data, ac); RTW89_SET_EDCA_PARAM(skb->data, val); @@ -3655,7 +3723,8 @@ fail: } #define H2C_TSF32_TOGL_LEN 4 -int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en) { struct sk_buff *skb; @@ -3671,9 +3740,9 @@ int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif skb_put(skb, H2C_TSF32_TOGL_LEN); cmd = skb->data; - RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif->mac_idx); + RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif_link->mac_idx); RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, en); - RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif->port); + RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif_link->port); RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, early_us); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -3727,11 +3796,10 @@ fail: } int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, bool connect) { - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL; + struct ieee80211_bss_conf *bss_conf; s32 thold = RTW89_DEFAULT_CQM_THOLD; u32 hyst = RTW89_DEFAULT_CQM_HYST; struct rtw89_h2c_bcnfltr *h2c; @@ -3742,9 +3810,20 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw)) return -EINVAL; - if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA) + if (!rtwvif_link || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) return -EINVAL; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + + if (bss_conf->cqm_rssi_hyst) + hyst = bss_conf->cqm_rssi_hyst; + if (bss_conf->cqm_rssi_thold) + thold = bss_conf->cqm_rssi_thold; + + rcu_read_unlock(); + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n"); @@ -3754,11 +3833,6 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcnfltr *)skb->data; - if (bss_conf->cqm_rssi_hyst) - hyst = bss_conf->cqm_rssi_hyst; - if (bss_conf->cqm_rssi_thold) - thold = bss_conf->cqm_rssi_thold; - h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) | le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) | le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) | @@ -3768,7 +3842,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, le32_encode_bits(hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) | le32_encode_bits(thold + MAX_RSSI, RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, @@ -3833,15 +3907,16 @@ fail: return ret; } -int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_traffic_stats *stats = &rtwvif->stats; struct rtw89_h2c_ofld *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; - if (rtwvif->net_type != RTW89_NET_TYPE_INFRA) + if (rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) return -EINVAL; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -3853,7 +3928,7 @@ int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) skb_put(skb, len); h2c = (struct rtw89_h2c_ofld *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | le32_encode_bits(stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) | le32_encode_bits(stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP); @@ -4688,6 +4763,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, return 0; } +static int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, struct list_head *chan_list) { @@ -4759,8 +4835,10 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, return 0; } +static int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list) + struct list_head *chan_list, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_h2c_chinfo_elem_be *elem; @@ -4785,7 +4863,8 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, h2c->ch_num = ch_num; h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */ - h2c->arg = u8_encode_bits(RTW89_PHY_0, RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK); + h2c->arg = u8_encode_bits(rtwvif_link->mac_idx, + RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK); list_for_each_entry(ch_info, chan_list, list) { elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, sizeof(*elem)); @@ -4858,7 +4937,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, #define RTW89_SCAN_DELAY_TSF_UNIT 104800 int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan) { struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; @@ -4880,7 +4959,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, h2c = (struct rtw89_h2c_scanofld *)skb->data; if (option->delay) { - ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "NLO failed to get port tsf: %d\n", ret); scan_mode = RTW89_SCAN_IMMEDIATE; @@ -4890,9 +4969,9 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, } } - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | - le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | - le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_SCANOFLD_W0_BAND) | le32_encode_bits(option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION); h2c->w1 = le32_encode_bits(true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) | @@ -4963,9 +5042,10 @@ static void rtw89_scan_get_6g_disabled_chan(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct cfg80211_scan_request *req = rtwvif->scan_req; @@ -5016,8 +5096,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, le32_encode_bits(option->repeat, RTW89_H2C_SCANOFLD_BE_W0_REPEAT) | le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_NOTIFY_END) | le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_LEARN_CH) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | - le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_W0_BAND); h2c->w1 = le32_encode_bits(option->num_macc_role, RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE) | @@ -5082,11 +5162,11 @@ flex_member: for (i = 0; i < option->num_opch; i++) { opch = ptr; - opch->w0 = le32_encode_bits(rtwvif->mac_id, + opch->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) | le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) | - le32_encode_bits(rtwvif->port, + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) | le32_encode_bits(RTW89_SCAN_OPMODE_INTV, RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) | @@ -5518,30 +5598,44 @@ fail: } int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, - const struct rtw89_chan *chan) + const struct rtw89_chan *chan, bool is_chl_k) { + struct rtw89_h2c_rf_rxdck_v0 *v0; struct rtw89_h2c_rf_rxdck *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + int ver = -1; int ret; + if (RTW89_CHK_FW_FEATURE(RFK_RXDCK_V0, &rtwdev->fw)) { + len = sizeof(*v0); + ver = 0; + } + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c RF RXDCK\n"); return -ENOMEM; } skb_put(skb, len); - h2c = (struct rtw89_h2c_rf_rxdck *)skb->data; + v0 = (struct rtw89_h2c_rf_rxdck_v0 *)skb->data; + + v0->len = len; + v0->phy = phy_idx; + v0->is_afe = false; + v0->kpath = RF_AB; + v0->cur_band = chan->band_type; + v0->cur_bw = chan->band_width; + v0->cur_ch = chan->channel; + v0->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + + if (ver == 0) + goto hdr; - h2c->len = len; - h2c->phy = phy_idx; - h2c->is_afe = false; - h2c->kpath = RF_AB; - h2c->cur_band = chan->band_type; - h2c->cur_bw = chan->band_width; - h2c->cur_ch = chan->channel; - h2c->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + h2c = (struct rtw89_h2c_rf_rxdck *)skb->data; + h2c->is_chl_k = is_chl_k; +hdr: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, H2C_FUNC_RFK_RXDCK_OFFLOAD, 0, 0, len); @@ -5871,12 +5965,10 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) } static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct cfg80211_scan_request *req, struct rtw89_pktofld_info *info, enum nl80211_band band, u8 ssid_idx) { - struct cfg80211_scan_request *req = rtwvif->scan_req; - if (band != NL80211_BAND_6GHZ) return false; @@ -5892,11 +5984,13 @@ static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, } static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct sk_buff *skb, u8 ssid_idx) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct ieee80211_scan_ies *ies = rtwvif->scan_ies; + struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_pktofld_info *info; struct sk_buff *new; int ret = 0; @@ -5921,8 +6015,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, goto out; } - rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band, - ssid_idx); + rtw89_is_6ghz_wildcard_probe_req(rtwdev, req, info, band, ssid_idx); ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new); if (ret) { @@ -5939,22 +6032,23 @@ out: } static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct sk_buff *skb; u8 num = req->n_ssids, i; int ret; for (i = 0; i < num; i++) { - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, req->ssids[i].ssid, req->ssids[i].ssid_len, req->ie_len); if (!skb) return -ENOMEM; - ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, i); + ret = rtw89_append_probe_req_ie(rtwdev, rtwvif_link, skb, i); kfree_skb(skb); if (ret) @@ -5965,13 +6059,12 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, } static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, + struct ieee80211_scan_ies *ies, struct cfg80211_scan_request *req, struct rtw89_mac_chinfo *ch_info) { - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; struct list_head *pkt_list = rtwdev->scan_info.pkt_list; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_6ghz_params *params; struct rtw89_pktofld_info *info, *tmp; struct ieee80211_hdr *hdr; @@ -6000,8 +6093,11 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, if (found) continue; - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, NULL, 0, req->ie_len); + if (!skb) + return -ENOMEM; + skb_put_data(skb, ies->ies[NL80211_BAND_6GHZ], ies->len[NL80211_BAND_6GHZ]); skb_put_data(skb, ies->common_ies, ies->common_ie_len); hdr = (struct ieee80211_hdr *)skb->data; @@ -6090,8 +6186,9 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, struct rtw89_mac_chinfo *ch_info) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; struct rtw89_pktofld_info *info; @@ -6117,7 +6214,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, } } - ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info); + ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info); if (ret) rtw89_warn(rtwdev, "RNR fails: %d\n", ret); @@ -6207,8 +6304,8 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, struct rtw89_mac_chinfo_be *ch_info) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_pktofld_info *info; u8 band, probe_count = 0, i; @@ -6265,7 +6362,7 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, } int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -6315,8 +6412,9 @@ out: } int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo *ch_info, *tmp; struct ieee80211_channel *channel; @@ -6392,7 +6490,7 @@ out: } int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -6432,7 +6530,8 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, list_add_tail(&ch_info->list, &chan_list); } - ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list); + ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list, + rtwvif_link); out: list_for_each_entry_safe(ch_info, tmp, &chan_list, list) { @@ -6444,8 +6543,9 @@ out: } int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo_be *ch_info, *tmp; struct ieee80211_channel *channel; @@ -6491,7 +6591,8 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, } rtwdev->scan_info.last_chan_idx = idx; - ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list); + ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list, + rtwvif_link); out: list_for_each_entry_safe(ch_info, tmp, &chan_list, list) { @@ -6503,79 +6604,86 @@ out: } static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; int ret; - ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif); + ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update probe request failed\n"); goto out; } - ret = mac->add_chan_list(rtwdev, rtwvif, connected); + ret = mac->add_chan_list(rtwdev, rtwvif_link, connected); out: return ret; } -void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct cfg80211_scan_request *req = &scan_req->req; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u32 rx_fltr = rtwdev->hal.rx_fltr; u8 mac_addr[ETH_ALEN]; + u32 reg; + + /* clone op and keep it during scan */ + rtwdev->scan_info.op_chan = *chan; - rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan); - rtwdev->scan_info.scanning_vif = vif; + rtwdev->scan_info.scanning_vif = rtwvif_link; rtwdev->scan_info.last_chan_idx = 0; rtwdev->scan_info.abort = false; rtwvif->scan_ies = &scan_req->ies; rtwvif->scan_req = req; ieee80211_stop_queues(rtwdev->hw); - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, false); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false); if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) get_random_mask_addr(mac_addr, req->mac_addr, req->mac_addr_mask); else - ether_addr_copy(mac_addr, vif->addr); - rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true); + ether_addr_copy(mac_addr, rtwvif_link->mac_addr); + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true); rx_fltr &= ~B_AX_A_BCN_CHK_EN; rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr); rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN); } -void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool aborted) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); struct cfg80211_scan_info info = { .aborted = aborted, }; + struct rtw89_vif *rtwvif; + u32 reg; - if (!vif) + if (!rtwvif_link) return; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rtwdev->hal.rx_fltr); + rtwvif = rtwvif_link->rtwvif; + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); - rtw89_core_scan_complete(rtwdev, vif, true); + rtw89_core_scan_complete(rtwdev, rtwvif_link, true); ieee80211_scan_completed(rtwdev->hw, &info); ieee80211_wake_queues(rtwdev->hw); - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, true); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true); rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); rtw89_release_pkt_list(rtwdev); @@ -6588,14 +6696,15 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, rtw89_chanctx_proceed(rtwdev); } -void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; int ret; scan_info->abort = true; - ret = rtw89_hw_scan_offload(rtwdev, vif, false); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, false); if (ret) rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret); @@ -6604,40 +6713,43 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) * RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan * work properly. */ - rtw89_hw_scan_complete(rtwdev, vif, true); + rtw89_hw_scan_complete(rtwdev, rtwvif_link, true); } static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - /* This variable implies connected or during attempt to connect */ - if (!is_zero_ether_addr(rtwvif->bssid)) - return true; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + /* This variable implies connected or during attempt to connect */ + if (!is_zero_ether_addr(rtwvif_link->bssid)) + return true; + } } return false; } -int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_scan_option opt = {0}; - struct rtw89_vif *rtwvif; bool connected; int ret = 0; - rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; - if (!rtwvif) + if (!rtwvif_link) return -EINVAL; connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); opt.enable = enable; opt.target_ch_mode = connected; if (enable) { - ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected); + ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, connected); if (ret) goto out; } @@ -6645,14 +6757,14 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) { opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP; opt.scan_mode = RTW89_SCAN_MODE_SA; - opt.band = RTW89_PHY_0; + opt.band = rtwvif_link->mac_idx; opt.num_macc_role = 0; opt.mlo_mode = rtwdev->mlo_dbcc_mode; opt.num_opch = connected ? 1 : 0; opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID; } - ret = mac->scan_offload(rtwdev, &opt, rtwvif, false); + ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false); out: return ret; } @@ -6758,7 +6870,7 @@ fail: } #define H2C_KEEP_ALIVE_LEN 4 -int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct sk_buff *skb; @@ -6766,7 +6878,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, int ret; if (enable) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id); if (ret) @@ -6784,7 +6896,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable); RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id); RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5); - RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id); + RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif_link->mac_id); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -6806,7 +6918,7 @@ fail: return ret; } -int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_h2c_arp_offload *h2c; @@ -6816,7 +6928,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, int ret; if (enable) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_ARP_RSP, &pkt_id); if (ret) @@ -6834,7 +6946,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(enable, RTW89_H2C_ARP_OFFLOAD_W0_ENABLE) | le32_encode_bits(0, RTW89_H2C_ARP_OFFLOAD_W0_ACTION) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | le32_encode_bits(pkt_id, RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -6859,11 +6971,11 @@ fail: #define H2C_DISCONNECT_DETECT_LEN 8 int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable) + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct sk_buff *skb; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN); @@ -6902,7 +7014,7 @@ fail: return ret; } -int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; @@ -6923,7 +7035,7 @@ int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(enable, RTW89_H2C_NLO_W0_ENABLE) | le32_encode_bits(enable, RTW89_H2C_NLO_W0_IGNORE_CIPHER) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_NLO_W0_MACID); + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_NLO_W0_MACID); if (enable) { h2c->nlo_cnt = nd_config->n_match_sets; @@ -6953,12 +7065,12 @@ fail: return ret; } -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_h2c_wow_global *h2c; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; @@ -7002,12 +7114,12 @@ fail: #define H2C_WAKEUP_CTRL_LEN 4 int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct sk_buff *skb; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN); @@ -7100,13 +7212,13 @@ fail: } int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info; struct rtw89_h2c_wow_gtk_ofld *h2c; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; u32 len = sizeof(*h2c); u8 pkt_id_sa_query = 0; struct sk_buff *skb; @@ -7128,14 +7240,14 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, if (!enable) goto hdr; - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_EAPOL_KEY, &pkt_id_eapol); if (ret) goto fail; if (gtk_info->igtk_keyid) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_SA_QUERY, &pkt_id_sa_query); if (ret) @@ -7173,7 +7285,7 @@ fail: return ret; } -int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wait_info *wait = &rtwdev->mac.ps_wait; @@ -7189,7 +7301,7 @@ int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, skb_put(skb, len); h2c = (struct rtw89_h2c_fwips *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | le32_encode_bits(enable, RTW89_H2C_FW_IPS_W0_ENABLE); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index ad47e77d740b..d338c3aec725 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4286,7 +4286,7 @@ struct rtw89_h2c_rf_dack { __le32 type; } __packed; -struct rtw89_h2c_rf_rxdck { +struct rtw89_h2c_rf_rxdck_v0 { u8 len; u8 phy; u8 is_afe; @@ -4297,6 +4297,11 @@ struct rtw89_h2c_rf_rxdck { u8 rxdck_dbg_en; } __packed; +struct rtw89_h2c_rf_rxdck { + struct rtw89_h2c_rf_rxdck_v0 v0; + u8 is_chl_k; +} __packed; + enum rtw89_rf_log_type { RTW89_RF_RUN_LOG = 0, RTW89_RF_RPT_LOG = 1, @@ -4313,6 +4318,42 @@ struct rtw89_c2h_rf_run_log { __le32 arg[4]; } __packed; +struct rtw89_c2h_rf_iqk_rpt_log { + bool iqk_tx_fail[2]; + bool iqk_rx_fail[2]; + bool is_iqk_init; + bool is_reload; + bool is_wb_txiqk[2]; + bool is_wb_rxiqk[2]; + bool is_nbiqk; + bool txiqk_en; + bool rxiqk_en; + bool lok_en; + bool iqk_xym_en; + bool iqk_sram_en; + bool iqk_fft_en; + bool is_fw_iqk; + bool is_iqk_enable; + bool iqk_cfir_en; + bool thermal_rek_en; + u8 iqk_band[2]; + u8 iqk_ch[2]; + u8 iqk_bw[2]; + u8 iqk_times; + u8 version; + u8 phy; + u8 fwk_status; + u8 rsvd; + __le32 reload_cnt; + __le32 iqk_fail_cnt; + __le32 lok_idac[2]; + __le32 lok_vbuf[2]; + __le32 rftxgain[2][4]; + __le32 rfrxgain[2][4]; + __le32 tx_xym[2][4]; + __le32 rx_xym[2][4]; +} __packed; + struct rtw89_c2h_rf_dpk_rpt_log { u8 ver; u8 idx[2]; @@ -4334,19 +4375,25 @@ struct rtw89_c2h_rf_dpk_rpt_log { struct rtw89_c2h_rf_dack_rpt_log { u8 fwdack_ver; - u8 fwdack_rpt_ver; + u8 fwdack_info_ver; u8 msbk_d[2][2][16]; u8 dadck_d[2][2]; u8 cdack_d[2][2][2]; - __le16 addck2_d[2][2][2]; + u8 addck2_hd[2][2][2]; + u8 addck2_ld[2][2][2]; u8 adgaink_d[2][2]; - __le16 biask_d[2][2]; + u8 biask_hd[2][2]; + u8 biask_ld[2][2]; u8 addck_timeout; u8 cdack_timeout; u8 dadck_timeout; u8 msbk_timeout; u8 adgaink_timeout; + u8 wbadcdck_timeout; + u8 drck_timeout; u8 dack_fail; + u8 wbdck_d[2]; + u8 rck_d; } __packed; struct rtw89_c2h_rf_rxdck_rpt_log { @@ -4357,6 +4404,14 @@ struct rtw89_c2h_rf_rxdck_rpt_log { u8 timeout[2]; } __packed; +struct rtw89_c2h_rf_tssi_rpt_log { + s8 alignment_power[2][2][4]; + u8 alignment_power_cw_h[2][2][4]; + u8 alignment_power_cw_l[2][2][4]; + u8 tssi_alimk_state[2][2]; + u8 default_txagc_offset[2][2]; +} __packed; + struct rtw89_c2h_rf_txgapk_rpt_log { __le32 r0x8010[2]; __le32 chk_cnt; @@ -4404,59 +4459,59 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len); int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta); + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta); + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); -int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *vif, - struct rtw89_sta *rtwsta, const u8 *scan_mac_addr); + 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); int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h); void rtw89_fw_c2h_work(struct work_struct *work); int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, enum rtw89_upd_mode upd_mode); -int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, bool dis_conn); +int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool dis_conn); int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en); int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp, bool pause); -int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 ac, u32 val); int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, bool connect); int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); -int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi); int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type); @@ -4472,17 +4527,13 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id); int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, struct sk_buff *skb_ofld); -int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list); -int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list); int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *opt, - struct rtw89_vif *vif, + struct rtw89_vif_link *vif, bool wowlan); int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, struct rtw89_scan_option *opt, - struct rtw89_vif *vif, + struct rtw89_vif_link *vif, bool wowlan); int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, struct rtw89_fw_h2c_rf_reg_info *info, @@ -4501,21 +4552,26 @@ int rtw89_fw_h2c_rf_txgapk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan); int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, - const struct rtw89_chan *chan); + const struct rtw89_chan *chan, bool is_chl_k); int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, u8 *buf, u16 len, bool rack, bool dack); 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, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 macid); void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool notify_fw); + 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_sta *rtwsta, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params); -int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, 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, @@ -4524,8 +4580,8 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, struct rtw89_lps_parm *lps_param); int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); -int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link); +int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len); struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len); @@ -4534,49 +4590,56 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, struct rtw89_mac_c2h_info *c2h_info); int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable); void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev); -void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_scan_request *req); -void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_scan_request *scan_req); +void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool aborted); -int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool enable); -void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, const struct rtw89_pkt_drop_params *params); -int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct ieee80211_p2p_noa_desc *desc, u8 act, u8 noa_id); -int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en); -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); -int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); +int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); -int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, struct rtw89_wow_cam_info *cam_info); int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev, @@ -4621,51 +4684,73 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) } static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); } static inline int rtw89_chip_h2c_default_dmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->h2c_default_dmac_tbl) - return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); return 0; } static inline int rtw89_chip_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_update_beacon(rtwdev, rtwvif); + return chip->ops->h2c_update_beacon(rtwdev, rtwvif_link); } static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_assoc_cmac_tbl(rtwdev, vif, sta); + return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); } -static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static inline +int rtw89_chip_h2c_ampdu_link_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->h2c_ampdu_cmac_tbl) - return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, rtwvif_link, + rtwsta_link); + + return 0; +} + +static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta) +{ + 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 = rtw89_chip_h2c_ampdu_link_cmac_tbl(rtwdev, rtwvif_link, + rtwsta_link); + if (ret) + return ret; + } return 0; } @@ -4675,8 +4760,20 @@ 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 chip->ops->h2c_ba_cam(rtwdev, rtwsta, valid, params); + return 0; } /* must consider compatibility; don't insert new in the mid */ diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index c70a23a763b0..e09f926bb4a0 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -1483,7 +1483,8 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags); clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags); rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR); - rtw89_set_entity_state(rtwdev, false); + rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false); + rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false); } return 0; @@ -4076,17 +4077,17 @@ static const struct rtw89_port_reg rtw89_port_base_ax = { }; static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u8 type) + struct rtw89_vif_link *rtwvif_link, u8 type) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif->port); + u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif_link->port); u32 reg_info, reg_ctrl; u32 val; int ret; - reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif->mac_idx); - reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif->mac_idx); + reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif_link->mac_idx); + reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg_ctrl, B_AX_PTCL_DBG_SEL_MASK, type); rtw89_write32_set(rtwdev, reg_ctrl, B_AX_PTCL_DBG_EN); @@ -4098,26 +4099,32 @@ static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, rtw89_warn(rtwdev, "Polling beacon packet empty fail\n"); } -static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, 1); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, 0); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 0); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, 2); - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK, 1); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, 1); - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); - - rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM0); - if (rtwvif->port == RTW89_PORT_0) - rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM1); - - rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TBTT_PROHIB_EN); + rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, + 1); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, + 0); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, + 0); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, 2); + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, + B_AX_TBTTERLY_MASK, 1); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, + B_AX_BCN_SPACE_MASK, 1); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); + + rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM0); + if (rtwvif_link->port == RTW89_PORT_0) + rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM1); + + rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TBTT_PROHIB_EN); fsleep(2000); } @@ -4131,286 +4138,329 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvi #define BCN_ERLY_SET_DLY (10 * 2) static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; bool need_backup = false; u32 backup_val; + u16 beacon_int; - if (!rtw89_read32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN)) + if (!rtw89_read32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN)) return; - if (chip->chip_id == RTL8852A && rtwvif->port != RTW89_PORT_0) { + if (chip->chip_id == RTL8852A && rtwvif_link->port != RTW89_PORT_0) { need_backup = true; - backup_val = rtw89_read32_port(rtwdev, rtwvif, p->tbtt_prohib); + backup_val = rtw89_read32_port(rtwdev, rtwvif_link, p->tbtt_prohib); } - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) - rtw89_mac_bcn_drop(rtwdev, rtwvif); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + rtw89_mac_bcn_drop(rtwdev, rtwvif_link); if (chip->chip_id == RTL8852A) { - rtw89_write32_port_clr(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 1); - rtw89_write16_port_clr(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK); - rtw89_write16_port_clr(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_SETUP_MASK); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_HOLD_MASK, 1); + rtw89_write16_port_clr(rtwdev, rtwvif_link, p->tbtt_early, + B_AX_TBTTERLY_MASK); + rtw89_write16_port_clr(rtwdev, rtwvif_link, p->bcn_early, + B_AX_BCNERLY_MASK); } - msleep(vif->bss_conf.beacon_int + 1); - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN | + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + beacon_int = bss_conf->beacon_int; + + rcu_read_unlock(); + + msleep(beacon_int + 1); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN | B_AX_BRK_SETUP); - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSFTR_RST); - rtw89_write32_port(rtwdev, rtwvif, p->bcn_cnt_tmr, 0); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSFTR_RST); + rtw89_write32_port(rtwdev, rtwvif_link, p->bcn_cnt_tmr, 0); if (need_backup) - rtw89_write32_port(rtwdev, rtwvif, p->tbtt_prohib, backup_val); + rtw89_write32_port(rtwdev, rtwvif_link, p->tbtt_prohib, backup_val); } static void rtw89_mac_port_cfg_tx_rpt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, + B_AX_TXBCN_RPT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, + B_AX_TXBCN_RPT_EN); } static void rtw89_mac_port_cfg_rx_rpt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, + B_AX_RXBCN_RPT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, + B_AX_RXBCN_RPT_EN); } static void rtw89_mac_port_cfg_net_type(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_NET_TYPE_MASK, - rtwvif->net_type); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_NET_TYPE_MASK, + rtwvif_link->net_type); } static void rtw89_mac_port_cfg_bcn_prct(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - bool en = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK; + bool en = rtwvif_link->net_type != RTW89_NET_TYPE_NO_LINK; u32 bits = B_AX_TBTT_PROHIB_EN | B_AX_BRK_SETUP; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bits); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bits); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bits); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bits); } static void rtw89_mac_port_cfg_rx_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; u32 bit = B_AX_RX_BSSID_FIT_EN; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bit); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bit); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bit); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bit); } void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); } static void rtw89_mac_port_cfg_rx_sync_by_nettype(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, en); } static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); } static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; - rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) - rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL; + struct ieee80211_bss_conf *bss_conf; + u16 bcn_int; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (bss_conf->beacon_int) + bcn_int = bss_conf->beacon_int; + else + bcn_int = BCN_INTERVAL; + + rcu_read_unlock(); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, B_AX_BCN_SPACE_MASK, bcn_int); } static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; + u8 win = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; - reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif_link->mac_idx); rtw89_write8(rtwdev, reg, win); } static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + u8 dtim_period; u32 addr; - addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif->mac_idx); + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + dtim_period = bss_conf->dtim_period; + + rcu_read_unlock(); + + addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif_link->mac_idx); rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE); - rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, - vif->bss_conf.dtim_period); + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, + dtim_period); } static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, BCN_SETUP_DEF); } static void rtw89_mac_port_cfg_bcn_hold_time(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, BCN_HOLD_DEF); } static void rtw89_mac_port_cfg_bcn_mask_area(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, BCN_MASK_DEF); } static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF); } static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); static const u32 masks[RTW89_PORT_NUM] = { B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK, B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK, B_AX_BSS_COLOB_AX_PORT_4_MASK, }; - u8 port = rtwvif->port; + struct ieee80211_bss_conf *bss_conf; + u8 port = rtwvif_link->port; u32 reg_base; u32 reg; u8 bss_color; - bss_color = vif->bss_conf.he_bss_color.color; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + bss_color = bss_conf->he_bss_color.color; + + rcu_read_unlock(); + reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color; - reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); } static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) return; if (port == 0) { - reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif_link->mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK); } } static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; u32 val; - reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif_link->mac_idx); val = rtw89_read32(rtwdev, reg); val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port)); if (port == 0) @@ -4419,31 +4469,31 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, } static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable) + struct rtw89_vif_link *rtwvif_link, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (enable) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN); } static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, BCN_ERLY_DEF); } static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; @@ -4452,20 +4502,20 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, if (rtwdev->chip->chip_id != RTL8852C) return; - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && - rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) return; val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) | B_AX_TBTT_SHIFT_OFST_SIGN; - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift, + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift, B_AX_TBTT_SHIFT_OFST_MASK, val); } void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u16 offset_tu) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; @@ -4473,8 +4523,8 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, u32 val, reg; val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu); - reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif->port * 4, - rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif_link->port * 4, + rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port); rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val); @@ -4482,16 +4532,16 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, } static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u8 offset, int *n_offset) { - if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src) + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif_link == rtwvif_src) return; /* adjust offset randomly to avoid beacon conflict */ offset = offset - offset / 4 + get_random_u32() % (offset / 2); - rtw89_mac_port_tsf_sync(rtwdev, rtwvif, rtwvif_src, + rtw89_mac_port_tsf_sync(rtwdev, rtwvif_link, rtwvif_src, (*n_offset) * offset); (*n_offset)++; @@ -4499,15 +4549,19 @@ static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) { - struct rtw89_vif *src = NULL, *tmp; + struct rtw89_vif_link *src = NULL, *tmp; u8 offset = 100, vif_aps = 0; + struct rtw89_vif *rtwvif; + unsigned int link_id; int n_offset = 1; - rtw89_for_each_rtwvif(rtwdev, tmp) { - if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) - src = tmp; - if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) - vif_aps++; + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + rtw89_vif_for_each_link(rtwvif, tmp, link_id) { + if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) + src = tmp; + if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) + vif_aps++; + } } if (vif_aps == 0) @@ -4515,104 +4569,106 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) offset /= (vif_aps + 1); - rtw89_for_each_rtwvif(rtwdev, tmp) - rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset); + rtw89_for_each_rtwvif(rtwdev, rtwvif) + rtw89_vif_for_each_link(rtwvif, tmp, link_id) + rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, + &n_offset); } -int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { int ret; - ret = rtw89_mac_port_update(rtwdev, rtwvif); + ret = rtw89_mac_port_update(rtwdev, rtwvif_link); if (ret) return ret; - rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id); - rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id); + rtw89_mac_dmac_tbl_init(rtwdev, rtwvif_link->mac_id); + rtw89_mac_cmac_tbl_init(rtwdev, rtwvif_link->mac_id); - ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false); + ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif_link->mac_id, false); if (ret) return ret; - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE); + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_CREATE); if (ret) return ret; - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); if (ret) return ret; - ret = rtw89_cam_init(rtwdev, rtwvif); + ret = rtw89_cam_init(rtwdev, rtwvif_link); if (ret) return ret; - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); if (ret) return ret; - ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, NULL); + ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, NULL); if (ret) return ret; - ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, NULL); + ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, NULL); if (ret) return ret; return 0; } -int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { int ret; - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE); + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_REMOVE); if (ret) return ret; - rtw89_cam_deinit(rtwdev, rtwvif); + rtw89_cam_deinit(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); if (ret) return ret; return 0; } -int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; if (port >= RTW89_PORT_NUM) return -EINVAL; - rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); - rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif, false); - rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif, false); - rtw89_mac_port_cfg_net_type(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif); - rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif); - rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif); - rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif); - rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif); - rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif); - rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif); - rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif); - rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true); + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif_link, false); + rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif_link, false); + rtw89_mac_port_cfg_net_type(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true); rtw89_mac_port_tsf_resync_all(rtwdev); fsleep(BCN_ERLY_SET_DLY); - rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif); + rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif_link); return 0; } -int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u64 *tsf) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; @@ -4620,12 +4676,12 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 tsf_low, tsf_high; int ret; - ret = rtw89_mac_check_mac_en(rtwdev, rtwvif->mac_idx, RTW89_CMAC_SEL); + ret = rtw89_mac_check_mac_en(rtwdev, rtwvif_link->mac_idx, RTW89_CMAC_SEL); if (ret) return ret; - tsf_low = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_l); - tsf_high = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_h); + tsf_low = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_l); + tsf_high = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_h); *tsf = (u64)tsf_high << 32 | tsf_low; return 0; @@ -4651,65 +4707,57 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, } void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_bss_conf *bss_conf; + struct cfg80211_chan_def oper; bool tolerated = true; u32 reg; - if (!vif->bss_conf.he_support || vif->type != NL80211_IFTYPE_STATION) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (!bss_conf->he_support || vif->type != NL80211_IFTYPE_STATION) { + rcu_read_unlock(); return; + } - if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR)) + oper = bss_conf->chanreq.oper; + if (!(oper.chan->flags & IEEE80211_CHAN_RADAR)) { + rcu_read_unlock(); return; + } - cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper, + rcu_read_unlock(); + + cfg80211_bss_iter(hw->wiphy, &oper, rtw89_mac_check_he_obss_narrow_bw_ru_iter, &tolerated); reg = rtw89_mac_reg_by_idx(rtwdev, mac->narrow_bw_ru_dis.addr, - rtwvif->mac_idx); + rtwvif_link->mac_idx); if (tolerated) rtw89_write32_clr(rtwdev, reg, mac->narrow_bw_ru_dis.mask); else rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask); } -void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); } -int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - int ret; - - rtwvif->mac_id = rtw89_acquire_mac_id(rtwdev); - if (rtwvif->mac_id == RTW89_MAX_MAC_ID_NUM) - return -ENOSPC; - - ret = rtw89_mac_vif_init(rtwdev, rtwvif); - if (ret) - goto release_mac_id; - - return 0; - -release_mac_id: - rtw89_release_mac_id(rtwdev, rtwvif->mac_id); - - return ret; + return rtw89_mac_vif_init(rtwdev, rtwvif_link); } -int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - int ret; - - ret = rtw89_mac_vif_deinit(rtwdev, rtwvif); - rtw89_release_mac_id(rtwdev, rtwvif->mac_id); - - return ret; + return rtw89_mac_vif_deinit(rtwdev, rtwvif_link); } static void @@ -4730,8 +4778,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, { const struct rtw89_c2h_scanofld *c2h = (const struct rtw89_c2h_scanofld *)skb->data; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif; struct rtw89_chan new; u8 reason, status, tx_fail, band, actual_period, expect_period; u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf; @@ -4739,9 +4787,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, u16 chan; int ret; - if (!rtwvif) + if (!rtwvif_link) return; + rtwvif = rtwvif_link->rtwvif; + tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL); status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS); chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH); @@ -4781,28 +4831,28 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (rtwdev->scan_info.abort) return; - if (rtwvif && rtwvif->scan_req && + if (rtwvif_link && rtwvif->scan_req && last_chan < rtwvif->scan_req->n_channels) { - ret = rtw89_hw_scan_offload(rtwdev, vif, true); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); if (ret) { - rtw89_hw_scan_abort(rtwdev, vif); + rtw89_hw_scan_abort(rtwdev, rtwvif_link); rtw89_warn(rtwdev, "HW scan failed: %d\n", ret); } } else { - rtw89_hw_scan_complete(rtwdev, vif, false); + rtw89_hw_scan_complete(rtwdev, rtwvif_link, false); } break; case RTW89_SCAN_ENTER_OP_NOTIFY: case RTW89_SCAN_ENTER_CH_NOTIFY: if (rtw89_is_op_chan(rtwdev, band, chan)) { - rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, &rtwdev->scan_info.op_chan); rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); ieee80211_wake_queues(rtwdev->hw); } else { rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20); - rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, &new); } break; @@ -4812,10 +4862,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, } static void -rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct sk_buff *skb) { - struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; enum nl80211_cqm_rssi_threshold_event nl_event; const struct rtw89_c2h_mac_bcnfltr_rpt *c2h = (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data; @@ -4827,7 +4878,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT); mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID); - if (mac_id != rtwvif->mac_id) + if (mac_id != rtwvif_link->mac_id) return; rtw89_debug(rtwdev, RTW89_DBG_FW, @@ -4839,7 +4890,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (!rtwdev->scanning && !rtwvif->offchan) ieee80211_connection_loss(vif); else - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); return; case RTW89_BCN_FLTR_NOTIFY: nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; @@ -4863,10 +4914,13 @@ static void rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h); } static void @@ -5490,7 +5544,8 @@ int rtw89_mac_cfg_ppdu_status_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab return 0; } -void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) +static +void __rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) { #define MAC_AX_TIME_TH_SH 5 #define MAC_AX_LEN_TH_SH 4 @@ -5520,6 +5575,13 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th); } +void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev) +{ + __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + if (rtwdev->dbcc_en) + __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_1); +} + void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop) { bool empty; @@ -5931,15 +5993,15 @@ static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx) } static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - u8 mac_idx = rtwvif->mac_idx; u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; - u8 port_sel = rtwvif->port; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; u8 sound_dim = 3, t; - u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + u8 *phy_cap; u32 reg; u16 val; int ret; @@ -5948,6 +6010,11 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, if (ret) return ret; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; + if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD); @@ -5956,17 +6023,19 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, phy_cap[5]); sound_dim = min(sound_dim, t); } - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { - ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); t = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK, - sta->deflink.vht_cap.cap); + link_sta->vht_cap.cap); sound_dim = min(sound_dim, t); } nc = min(nc, sound_dim); nr = min(nr, sound_dim); + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); @@ -5989,34 +6058,41 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, } static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; u32 reg; - u8 mac_idx = rtwvif->mac_idx; int ret; ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) return ret; - if (sta->deflink.he_cap.has_he) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->he_cap.has_he) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); } - if (sta->deflink.ht_cap.ht_supported) { + if (link_sta->ht_cap.ht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); } + + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN); @@ -6028,35 +6104,53 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, } static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; - if (rtw89_sta_has_beamformer_cap(sta)) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); + + rcu_read_unlock(); + + if (has_beamformer_cap) { rtw89_debug(rtwdev, RTW89_DBG_BF, "initialize bfee for new association\n"); - rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx); - rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta); - rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta); + rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_ax(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_csi_rrsc_ax(rtwdev, rtwvif_link, rtwsta_link); } } -void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - - rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, false); + rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, false); } void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - u8 mac_idx = rtwvif->mac_idx; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + u8 mac_idx; __le32 *p; + rtwvif_link = rtwvif->links[conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, conf->link_id); + return; + } + + mac_idx = rtwvif_link->mac_idx; + rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n"); p = (__le32 *)conf->mu_group.membership; @@ -6080,7 +6174,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * struct rtw89_mac_bf_monitor_iter_data { struct rtw89_dev *rtwdev; - struct ieee80211_sta *down_sta; + struct rtw89_sta_link *down_rtwsta_link; int count; }; @@ -6089,23 +6183,41 @@ void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_mac_bf_monitor_iter_data *iter_data = (struct rtw89_mac_bf_monitor_iter_data *)data; - struct ieee80211_sta *down_sta = iter_data->down_sta; + struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct ieee80211_link_sta *link_sta; + struct rtw89_sta_link *rtwsta_link; + bool has_beamformer_cap = false; int *count = &iter_data->count; + unsigned int link_id; - if (down_sta == sta) - return; + rcu_read_lock(); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + if (rtwsta_link == down_rtwsta_link) + continue; + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (rtw89_sta_has_beamformer_cap(link_sta)) { + has_beamformer_cap = true; + break; + } + } - if (rtw89_sta_has_beamformer_cap(sta)) + if (has_beamformer_cap) (*count)++; + + rcu_read_unlock(); } void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool disconnect) + struct rtw89_sta_link *rtwsta_link, + bool disconnect) { struct rtw89_mac_bf_monitor_iter_data data; data.rtwdev = rtwdev; - data.down_sta = disconnect ? sta : NULL; + data.down_rtwsta_link = disconnect ? rtwsta_link : NULL; data.count = 0; ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_mac_bf_monitor_calc_iter, @@ -6121,10 +6233,12 @@ void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) { struct rtw89_traffic_stats *stats = &rtwdev->stats; - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv; bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); + struct rtw89_vif *rtwvif; bool keep_timer = true; + unsigned int link_id; bool old_keep_timer; old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags); @@ -6134,30 +6248,32 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) if (keep_timer != old_keep_timer) { rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bfee_standby_timer(rtwdev, rtwvif->mac_idx, - keep_timer); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx, + keep_timer); } if (en == old) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, en); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en); } static int -__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 tx_time) { #define MAC_AX_DFLT_TX_TIME 5280 - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_time) { - rtwsta->ampdu_max_time = (max_tx_time - 512) >> 9; - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); + if (rtwsta_link->cctl_tx_time) { + rtwsta_link->ampdu_max_time = (max_tx_time - 512) >> 9; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6173,31 +6289,31 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return ret; } -int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, bool resume, u32 tx_time) { int ret = 0; if (!resume) { - rtwsta->cctl_tx_time = true; - ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); + rtwsta_link->cctl_tx_time = true; + ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); } else { - ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); - rtwsta->cctl_tx_time = false; + ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); + rtwsta_link->cctl_tx_time = false; } return ret; } -int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 *tx_time) { - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_time) { - *tx_time = (rtwsta->ampdu_max_time + 1) << 9; + if (rtwsta_link->cctl_tx_time) { + *tx_time = (rtwsta_link->ampdu_max_time + 1) << 9; } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6213,33 +6329,33 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, } int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, bool resume, u8 tx_retry) { int ret = 0; - rtwsta->data_tx_cnt_lmt = tx_retry; + rtwsta_link->data_tx_cnt_lmt = tx_retry; if (!resume) { - rtwsta->cctl_tx_retry_limit = true; - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); + rtwsta_link->cctl_tx_retry_limit = true; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); } else { - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); - rtwsta->cctl_tx_retry_limit = false; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); + rtwsta_link->cctl_tx_retry_limit = false; } return ret; } int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 *tx_retry) + struct rtw89_sta_link *rtwsta_link, u8 *tx_retry) { - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_retry_limit) { - *tx_retry = rtwsta->data_tx_cnt_lmt; + if (rtwsta_link->cctl_tx_retry_limit) { + *tx_retry = rtwsta_link->data_tx_cnt_lmt; } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6255,10 +6371,10 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, } int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; - u8 mac_idx = rtwvif->mac_idx; + u8 mac_idx = rtwvif_link->mac_idx; u16 set = mac->muedca_ctrl.mask; u32 reg; u32 ret; @@ -6326,7 +6442,9 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val) } static -void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) +void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { static const enum rtw89_pkt_drop_sel sels[] = { RTW89_PKT_DROP_SEL_MACID_BE_ONCE, @@ -6334,15 +6452,14 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) RTW89_PKT_DROP_SEL_MACID_VI_ONCE, RTW89_PKT_DROP_SEL_MACID_VO_ONCE, }; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_pkt_drop_params params = {0}; int i; - params.mac_band = RTW89_MAC_0; - params.macid = rtwsta->mac_id; - params.port = rtwvif->port; + params.mac_band = rtwvif_link->mac_idx; + params.macid = rtwsta_link->mac_id; + params.port = rtwvif_link->port; params.mbssid = 0; - params.tf_trs = rtwvif->trigger; + params.tf_trs = rtwvif_link->trigger; for (i = 0; i < ARRAY_SIZE(sels); i++) { params.sel = sels[i]; @@ -6352,15 +6469,21 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_vif *target = data; + unsigned int link_id; if (rtwvif != target) return; - rtw89_mac_pkt_drop_sta(rtwdev, rtwsta); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + rtw89_mac_pkt_drop_sta(rtwdev, rtwvif_link, rtwsta_link); + } } void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) @@ -6398,6 +6521,9 @@ int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable) struct rtw89_mac_c2h_info c2h_info = {}; u32 ret; + if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw)) + return 0; + h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL; h2c_info.content_len = sizeof(h2c_info.u.hdr); h2c_info.u.hdr.w0 = u32_encode_bits(wow_enable, RTW89_H2CREG_WOW_CPUIO_RX_CTRL_EN); @@ -6434,6 +6560,9 @@ static int rtw89_wow_config_mac_ax(struct rtw89_dev *rtwdev, bool enable_wow) rtw89_write32(rtwdev, R_AX_TF_FWD, 0); rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0); + if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw)) + return 0; + if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) rtw89_write8(rtwdev, R_BE_DBG_WOW_READY, WOWLAN_NOT_READY); else diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 67c2a4507124..e59c1fcfea46 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -951,8 +951,9 @@ struct rtw89_mac_gen_def { void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev); void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable); void (*dle_clk_en)(struct rtw89_dev *rtwdev, bool enable); - void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + void (*bf_assoc)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*typ_fltr_opt)(struct rtw89_dev *rtwdev, enum rtw89_machdr_frame_type type, @@ -1004,12 +1005,12 @@ struct rtw89_mac_gen_def { bool (*is_txq_empty)(struct rtw89_dev *rtwdev); int (*add_chan_list)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int (*add_chan_list_pno)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int (*scan_offload)(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan); int (*wow_config_mac)(struct rtw89_dev *rtwdev, bool enable_wow); @@ -1033,81 +1034,89 @@ u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_id } static inline u32 -rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base) +rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); return rtw89_read32(rtwdev, reg); } static inline u32 -rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); return rtw89_read32_mask(rtwdev, reg, mask); } static inline void -rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base, +rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32(rtwdev, reg, data); } static inline void -rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask, u32 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, mask, data); } static inline void -rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask, u16 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write16_mask(rtwdev, reg, mask, data); } static inline void -rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_clr(rtwdev, reg, bit); } static inline void -rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u16 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write16_clr(rtwdev, reg, bit); } static inline void -rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_set(rtwdev, reg, bit); } @@ -1139,21 +1148,21 @@ int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_qempty *qempty); void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev, enum mac_ax_err_info err); -int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); -int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u16 offset_tu); -int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u64 *tsf); void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en); + struct rtw89_vif_link *rtwvif_link, bool en); void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif); -void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); +void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); -int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev); int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev); @@ -1213,7 +1222,22 @@ int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) return mac->cfg_ppdu_status(rtwdev, mac_idx, enable); } -void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx); +static inline +int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable) +{ + int ret; + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, enable); + if (ret) + return ret; + + if (!rtwdev->dbcc_en) + return 0; + + return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable); +} + +void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev); void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop); int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex); int rtw89_mac_coex_init_v1(struct rtw89_dev *rtwdev, @@ -1251,27 +1275,30 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter); void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev); static inline -void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; if (mac->bf_assoc) - mac->bf_assoc(rtwdev, vif, sta); + mac->bf_assoc(rtwdev, rtwvif_link, rtwsta_link); } -void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf); void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool disconnect); + struct rtw89_sta_link *rtwsta_link, + bool disconnect); void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev); void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en); -int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); -int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en); + struct rtw89_vif_link *rtwvif_link, bool en); int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause); static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) @@ -1376,15 +1403,15 @@ static inline bool rtw89_mac_get_power_state(struct rtw89_dev *rtwdev) return !!val; } -int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, bool resume, u32 tx_time); -int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 *tx_time); int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, bool resume, u8 tx_retry); int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 *tx_retry); + struct rtw89_sta_link *rtwsta_link, u8 *tx_retry); enum rtw89_mac_xtal_si_offset { XTAL0 = 0x0, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 48ad0d0f76bf..1ee63a85308f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -23,13 +23,13 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw, struct rtw89_dev *rtwdev = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct ieee80211_sta *sta = control->sta; u32 flags = IEEE80211_SKB_CB(skb)->flags; int ret, qsel; if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n"); skb_queue_tail(&rtwsta->roc_queue, skb); @@ -105,11 +105,61 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed) return 0; } +static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct ieee80211_bss_conf *bss_conf; + int ret; + + rtw89_leave_ps_mode(rtwdev); + + rtw89_vif_type_mapping(rtwvif_link, false); + + INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); + INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); + + rtwvif_link->hit_rule = 0; + rtwvif_link->bcn_hit_cond = 0; + rtwvif_link->chanctx_assigned = false; + rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); + + rcu_read_unlock(); + + ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); + if (ret) + return ret; + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START); + return 0; +} + +static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + mutex_unlock(&rtwdev->mutex); + cancel_work_sync(&rtwvif_link->update_beacon_work); + mutex_lock(&rtwdev->mutex); + + rtw89_leave_ps_mode(rtwdev); + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP); + + rtw89_mac_remove_vif(rtwdev, rtwvif_link); +} + static int rtw89_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + u8 mac_id, port; int ret = 0; rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n", @@ -123,49 +173,56 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_CQM_RSSI; - rtwvif->rtwdev = rtwdev; - rtwvif->roc.state = RTW89_ROC_IDLE; - rtwvif->offchan = false; + mac_id = rtw89_acquire_mac_id(rtwdev); + if (mac_id == RTW89_MAX_MAC_ID_NUM) { + ret = -ENOSPC; + goto err; + } + + port = rtw89_core_acquire_bit_map(rtwdev->hw_port, RTW89_PORT_NUM); + if (port == RTW89_PORT_NUM) { + ret = -ENOSPC; + goto release_macid; + } + + rtw89_init_vif(rtwdev, rtwvif, mac_id, port); + + rtw89_core_txq_init(rtwdev, vif->txq); + if (!rtw89_rtwvif_in_list(rtwdev, rtwvif)) list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list); - INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work); + ether_addr_copy(rtwvif->mac_addr, vif->addr); + + rtwvif->offchan = false; + rtwvif->roc.state = RTW89_ROC_IDLE; INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work); - rtw89_leave_ps_mode(rtwdev); rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); - rtw89_vif_type_mapping(vif, false); - rtwvif->port = rtw89_core_acquire_bit_map(rtwdev->hw_port, - RTW89_PORT_NUM); - if (rtwvif->port == RTW89_PORT_NUM) { - ret = -ENOSPC; - list_del_init(&rtwvif->list); - goto out; - } - rtwvif->bcn_hit_cond = 0; - rtwvif->mac_idx = RTW89_MAC_0; - rtwvif->phy_idx = RTW89_PHY_0; - rtwvif->chanctx_idx = RTW89_CHANCTX_0; - rtwvif->chanctx_assigned = false; - rtwvif->hit_rule = 0; - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; - ether_addr_copy(rtwvif->mac_addr, vif->addr); - INIT_LIST_HEAD(&rtwvif->general_pkt_list); - - ret = rtw89_mac_add_vif(rtwdev, rtwvif); - if (ret) { - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); - list_del_init(&rtwvif->list); - goto out; + rtwvif_link = rtw89_vif_set_link(rtwvif, 0); + if (!rtwvif_link) { + ret = -EINVAL; + goto release_port; } - rtw89_core_txq_init(rtwdev, vif->txq); - - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START); + ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link); + if (ret) + goto unset_link; rtw89_recalc_lps(rtwdev); -out: + + mutex_unlock(&rtwdev->mutex); + return 0; + +unset_link: + rtw89_vif_unset_link(rtwvif, 0); +release_port: + list_del_init(&rtwvif->list); + rtw89_core_release_bit_map(rtwdev->hw_port, port); +release_macid: + rtw89_release_mac_id(rtwdev, mac_id); +err: mutex_unlock(&rtwdev->mutex); return ret; @@ -175,20 +232,35 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + u8 macid = rtw89_vif_get_main_macid(rtwvif); + u8 port = rtw89_vif_get_main_port(rtwvif); + struct rtw89_vif_link *rtwvif_link; rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n", vif->addr, vif->type, vif->p2p); - cancel_work_sync(&rtwvif->update_beacon_work); cancel_delayed_work_sync(&rtwvif->roc.roc_work); mutex_lock(&rtwdev->mutex); - rtw89_leave_ps_mode(rtwdev); - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP); - rtw89_mac_remove_vif(rtwdev, rtwvif); - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); + + rtwvif_link = rtwvif->links[0]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, 0); + goto bottom; + } + + __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); + + rtw89_vif_unset_link(rtwvif, 0); + +bottom: list_del_init(&rtwvif->list); + rtw89_core_release_bit_map(rtwdev->hw_port, port); + rtw89_release_mac_id(rtwdev, macid); + rtw89_recalc_lps(rtwdev); rtw89_enter_ips_by_hwflags(rtwdev); @@ -311,24 +383,30 @@ static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { }; static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u8 aifsn) + struct rtw89_vif_link *rtwvif_link, u8 aifsn) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); + struct ieee80211_bss_conf *bss_conf; u8 slot_time; u8 sifs; - slot_time = vif->bss_conf.use_short_slot ? 9 : 20; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + slot_time = bss_conf->use_short_slot ? 9 : 20; + + rcu_read_unlock(); + sifs = chan->band_type == RTW89_BAND_2G ? 10 : 16; return aifsn * slot_time + sifs; } static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; + struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; u32 val; u8 ecw_max, ecw_min; u8 aifs; @@ -336,12 +414,12 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */ ecw_max = ilog2(params->cw_max + 1); ecw_min = ilog2(params->cw_min + 1); - aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif, params->aifs); + aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, params->aifs); val = FIELD_PREP(FW_EDCA_PARAM_TXOPLMT_MSK, params->txop) | FIELD_PREP(FW_EDCA_PARAM_CWMAX_MSK, ecw_max) | FIELD_PREP(FW_EDCA_PARAM_CWMIN_MSK, ecw_min) | FIELD_PREP(FW_EDCA_PARAM_AIFS_MSK, aifs); - rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val); + rtw89_fw_h2c_set_edca(rtwdev, rtwvif_link, ac_to_fw_idx[ac], val); } #define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \ @@ -355,9 +433,9 @@ static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = { }; static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; + struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; struct ieee80211_he_mu_edca_param_ac_rec *mu_edca; int gen = rtwdev->chip->chip_gen; u8 aifs, aifsn; @@ -370,32 +448,199 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, mu_edca = ¶ms->mu_edca_param_rec; aifsn = FIELD_GET(GENMASK(3, 0), mu_edca->aifsn); - aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif, aifsn) : 0; + aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, aifsn) : 0; timer_32us = mu_edca->mu_edca_timer << 8; val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs); - reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], + rtwvif_link->mac_idx); rtw89_write32(rtwdev, reg, val); - rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true); + rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif_link, true); } static void __rtw89_conf_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - ____rtw89_conf_tx_edca(rtwdev, rtwvif, ac); - ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif, ac); + ____rtw89_conf_tx_edca(rtwdev, rtwvif_link, ac); + ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif_link, ac); } static void rtw89_conf_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { u16 ac; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - __rtw89_conf_tx(rtwdev, rtwvif, ac); + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); +} + +static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + bool acquire_macid = false; + u8 macid; + int ret; + int i; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + /* for station mode, assign the mac_id from itself */ + macid = rtw89_vif_get_main_macid(rtwvif); + } else { + macid = rtw89_acquire_mac_id(rtwdev); + if (macid == RTW89_MAX_MAC_ID_NUM) + return -ENOSPC; + + acquire_macid = true; + } + + rtw89_init_sta(rtwdev, rtwvif, rtwsta, macid); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw89_core_txq_init(rtwdev, sta->txq[i]); + + skb_queue_head_init(&rtwsta->roc_queue); + + rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id); + if (!rtwsta_link) { + ret = -EINVAL; + goto err; + } + + rtwvif_link = rtwsta_link->rtwvif_link; + + ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + goto unset_link; + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + + return 0; + +unset_link: + rtw89_sta_unset_link(rtwsta, sta->deflink.link_id); +err: + if (acquire_macid) + rtw89_release_mac_id(rtwdev, macid); + + return ret; +} + +static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool station_mode) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + 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; + + if (station_mode) + rtw89_vif_type_mapping(rtwvif_link, true); + + ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + rtwdev->total_sta_assoc++; + if (sta->tdls) + rtwvif->tdls_peer++; + + return 0; +} + +static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + 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 = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + rtwsta->disassoc = true; + + rtwdev->total_sta_assoc--; + if (sta->tdls) + rtwvif->tdls_peer--; + + return 0; +} + +static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_core_free_sta_pending_ba(rtwdev, sta); + rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); + rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + return 0; +} + +static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + u8 macid = rtw89_sta_get_main_macid(rtwsta); + 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 = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + + rtw89_sta_unset_link(rtwsta, link_id); + } + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + rtw89_release_mac_id(rtwdev, macid); + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + } + + return 0; } static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, @@ -412,16 +657,34 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, return; } - rtw89_vif_type_mapping(vif, true); + __rtw89_ops_sta_assoc(rtwdev, vif, sta, true); +} + +static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); +} + +static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - rtw89_core_sta_assoc(rtwdev, vif, sta); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); } static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); @@ -429,10 +692,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (vif->cfg.assoc) { rtw89_station_mode_sta_assoc(rtwdev, vif); - rtw89_phy_set_bss_color(rtwdev, vif); - rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); - rtw89_mac_port_update(rtwdev, rtwvif); - rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif); + __rtw89_ops_bss_assoc(rtwdev, vif); rtw89_queue_chanctx_work(rtwdev); } else { @@ -459,39 +719,49 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, u64 changed) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); + rtwvif_link = rtwvif->links[conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, conf->link_id); + goto out; + } + if (changed & BSS_CHANGED_BSSID) { - ether_addr_copy(rtwvif->bssid, conf->bssid); - rtw89_cam_bssid_changed(rtwdev, rtwvif); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); - WRITE_ONCE(rtwvif->sync_bcn_tsf, 0); + ether_addr_copy(rtwvif_link->bssid, conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0); } if (changed & BSS_CHANGED_BEACON) - rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_ERP_SLOT) - rtw89_conf_tx(rtwdev, rtwvif); + rtw89_conf_tx(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_HE_BSS_COLOR) - rtw89_phy_set_bss_color(rtwdev, vif); + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_MU_GROUPS) rtw89_mac_bf_set_gid_table(rtwdev, vif, conf); if (changed & BSS_CHANGED_P2P_PS) - rtw89_core_update_p2p_ps(rtwdev, vif); + rtw89_core_update_p2p_ps(rtwdev, rtwvif_link, conf); if (changed & BSS_CHANGED_CQM) - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); if (changed & BSS_CHANGED_TPE) - rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); +out: mutex_unlock(&rtwdev->mutex); } @@ -500,12 +770,21 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; const struct rtw89_chan *chan; mutex_lock(&rtwdev->mutex); - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + goto out; + } + + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); if (chan->band_type == RTW89_BAND_6G) { mutex_unlock(&rtwdev->mutex); return -EOPNOTSUPP; @@ -514,16 +793,18 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, if (rtwdev->scanning) rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); - ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid); - rtw89_cam_bssid_changed(rtwdev, rtwvif); - rtw89_mac_port_update(rtwdev, rtwvif); - rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); - rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE); - rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); - rtw89_chip_rfk_channel(rtwdev, rtwvif); + ether_addr_copy(rtwvif_link->bssid, link_conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + 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_chip_rfk_channel(rtwdev, rtwvif_link); rtw89_queue_chanctx_work(rtwdev); + +out: mutex_unlock(&rtwdev->mutex); return 0; @@ -534,12 +815,24 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_mac_stop_ap(rtwdev, rtwvif); - rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); - rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + goto out; + } + + rtw89_mac_stop_ap(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + +out: mutex_unlock(&rtwdev->mutex); } @@ -547,10 +840,13 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); return 0; } @@ -561,15 +857,29 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + int ret = 0; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); - rtwvif->tx_params[ac] = *params; - __rtw89_conf_tx(rtwdev, rtwvif, ac); + + rtwvif_link = rtwvif->links[link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_id); + ret = -ENOLINK; + goto out; + } + + rtwvif_link->tx_params[ac] = *params; + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); + +out: mutex_unlock(&rtwdev->mutex); - return 0; + return ret; } static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, @@ -582,26 +892,26 @@ static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return rtw89_core_sta_add(rtwdev, vif, sta); + return __rtw89_ops_sta_add(rtwdev, vif, sta); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) return 0; /* defer to bss_info_changed to have vif info */ - return rtw89_core_sta_assoc(rtwdev, vif, sta); + return __rtw89_ops_sta_assoc(rtwdev, vif, sta, false); } if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) - return rtw89_core_sta_disassoc(rtwdev, vif, sta); + return __rtw89_ops_sta_disassoc(rtwdev, vif, sta); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_NONE) - return rtw89_core_sta_disconnect(rtwdev, vif, sta); + return __rtw89_ops_sta_disconnect(rtwdev, vif, sta); if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST) - return rtw89_core_sta_remove(rtwdev, vif, sta); + return __rtw89_ops_sta_remove(rtwdev, vif, sta); return 0; } @@ -667,7 +977,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, { struct rtw89_dev *rtwdev = hw->priv; struct ieee80211_sta *sta = params->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); u16 tid = params->tid; struct ieee80211_txq *txq = sta->txq[tid]; struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; @@ -681,7 +992,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, mutex_lock(&rtwdev->mutex); clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); clear_bit(tid, rtwsta->ampdu_map); - rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); mutex_unlock(&rtwdev->mutex); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -692,7 +1003,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, rtwsta->ampdu_params[tid].amsdu = params->amsdu; set_bit(tid, rtwsta->ampdu_map); rtw89_leave_ps_mode(rtwdev); - rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); mutex_unlock(&rtwdev->mutex); break; case IEEE80211_AMPDU_RX_START: @@ -720,7 +1031,7 @@ static int rtw89_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) - rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + rtw89_mac_update_rts_threshold(rtwdev); mutex_unlock(&rtwdev->mutex); return 0; @@ -731,9 +1042,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; - sinfo->txrate = rtwsta->ra_report.txrate; + sinfo->txrate = rtwsta_link->ra_report.txrate; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } @@ -743,7 +1059,7 @@ void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) struct rtw89_vif *rtwvif; if (vif) { - rtwvif = (struct rtw89_vif *)vif->drv_priv; + rtwvif = vif_to_rtwvif(vif); rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); } else { rtw89_for_each_rtwvif(rtwdev, rtwvif) @@ -777,14 +1093,20 @@ struct rtw89_iter_bitrate_mask_data { static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_iter_bitrate_mask_data *br_data = data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; if (vif != br_data->vif || vif->p2p) return; - rtwsta->use_cfg_mask = true; - rtwsta->mask = *br_data->mask; + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwsta_link->use_cfg_mask = true; + rtwsta_link->mask = *br_data->mask; + } + rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); } @@ -854,10 +1176,20 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw, const u8 *mac_addr) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, false); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n"); + goto out; + } + + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false); + +out: mutex_unlock(&rtwdev->mutex); } @@ -865,9 +1197,20 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_core_scan_complete(rtwdev, vif, false); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n"); + goto out; + } + + rtw89_core_scan_complete(rtwdev, rtwvif_link, false); + +out: mutex_unlock(&rtwdev->mutex); } @@ -884,22 +1227,35 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - int ret = 0; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + int ret; if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) return 1; - if (rtwdev->scanning || rtwvif->offchan) - return -EBUSY; - mutex_lock(&rtwdev->mutex); - rtw89_hw_scan_start(rtwdev, vif, req); - ret = rtw89_hw_scan_offload(rtwdev, vif, true); + + if (rtwdev->scanning || rtwvif->offchan) { + ret = -EBUSY; + goto out; + } + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "hw scan: find no link on HW-0\n"); + ret = -ENOLINK; + goto out; + } + + rtw89_hw_scan_start(rtwdev, rtwvif_link, req); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); if (ret) { - rtw89_hw_scan_abort(rtwdev, vif); + rtw89_hw_scan_abort(rtwdev, rtwvif_link); rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret); } + +out: mutex_unlock(&rtwdev->mutex); return ret; @@ -909,6 +1265,8 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) return; @@ -917,7 +1275,16 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, return; mutex_lock(&rtwdev->mutex); - rtw89_hw_scan_abort(rtwdev, vif); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n"); + goto out; + } + + rtw89_hw_scan_abort(rtwdev, rtwvif_link); + +out: mutex_unlock(&rtwdev->mutex); } @@ -970,11 +1337,24 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; int ret; mutex_lock(&rtwdev->mutex); - ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + ret = -ENOLINK; + goto out; + } + + ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx); + +out: mutex_unlock(&rtwdev->mutex); return ret; @@ -986,10 +1366,20 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + return; + } + + rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx); mutex_unlock(&rtwdev->mutex); } @@ -1003,7 +1393,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); struct rtw89_roc *roc = &rtwvif->roc; - if (!vif) + if (!rtwvif) return -EINVAL; mutex_lock(&rtwdev->mutex); @@ -1053,8 +1443,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta) { struct cfg80211_tid_config *tid_config = data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwvif->rtwdev; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; rtw89_core_set_tid_config(rtwdev, sta, tid_config); } diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 31f0a5225b11..30943462640f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -773,7 +773,7 @@ static int dmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) return ret; } - ret = rtw89_mac_preload_init(rtwdev, RTW89_MAC_0, rtwdev->mac.qta_mode); + ret = rtw89_mac_preload_init(rtwdev, mac_idx, rtwdev->mac.qta_mode); if (ret) { rtw89_err(rtwdev, "[ERR]preload init %d\n", ret); return ret; @@ -2091,13 +2091,13 @@ static int rtw89_mac_init_bfee_be(struct rtw89_dev *rtwdev, u8 mac_idx) } static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; - u8 mac_idx = rtwvif->mac_idx; - u8 port_sel = rtwvif->port; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; u8 sound_dim = 3, t; u8 *phy_cap; u32 reg; @@ -2108,7 +2108,10 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, if (ret) return ret; - phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { @@ -2119,11 +2122,11 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, sound_dim = min(sound_dim, t); } - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { - ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); - t = u32_get_bits(sta->deflink.vht_cap.cap, + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + t = u32_get_bits(link_sta->vht_cap.cap, IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK); sound_dim = min(sound_dim, t); } @@ -2131,6 +2134,8 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, nc = min(nc, sound_dim); nr = min(nr, sound_dim); + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); @@ -2155,12 +2160,12 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, } static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); - u8 mac_idx = rtwvif->mac_idx; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; int ret; u32 reg; @@ -2168,22 +2173,28 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, if (ret) return ret; - if (sta->deflink.he_cap.has_he) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->he_cap.has_he) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); } - if (sta->deflink.ht_cap.ht_supported) { + if (link_sta->ht_cap.ht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); } + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); rtw89_write32_clr(rtwdev, reg, B_BE_BFMEE_CSI_FORCE_RETE_EN); @@ -2195,17 +2206,25 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, } static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); + + rcu_read_unlock(); - if (rtw89_sta_has_beamformer_cap(sta)) { + if (has_beamformer_cap) { rtw89_debug(rtwdev, RTW89_DBG_BF, "initialize bfee for new association\n"); - rtw89_mac_init_bfee_be(rtwdev, rtwvif->mac_idx); - rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta); - rtw89_mac_csi_rrsc_be(rtwdev, vif, sta); + rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_be(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_csi_rrsc_be(rtwdev, rtwvif_link, rtwsta_link); } } diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 02afeb3acce4..5ed7eaa18c85 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -2358,13 +2358,15 @@ static int rtw89_pci_deglitch_setting(struct rtw89_dev *rtwdev) return 0; } -static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) +static void rtw89_pci_disable_eq_ax(struct rtw89_dev *rtwdev) { u16 g1_oobs, g2_oobs; u32 backup_aspm; u32 phy_offset; + u16 offset_cal; u16 oobs_val; int ret; + u8 gen; if (rtwdev->chip->chip_id != RTL8852C) return; @@ -2400,6 +2402,28 @@ static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) rtw89_write16_set(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + /* offset K */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 : + R_RAC_DIRECT_OFFSET_G2; + + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G1 + + RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 : + R_RAC_DIRECT_OFFSET_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT, + MANUAL_LVL_MASK, offset_cal); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + OFFSET_CAL_MODE); + } + out: rtw89_write32(rtwdev, R_AX_PCIE_MIX_CFG_V1, backup_aspm); } @@ -3724,19 +3748,16 @@ static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev, pci_free_irq_vectors(pdev); } -static u16 gray_code_to_bin(u16 gray_code, u32 bit_num) +static u16 gray_code_to_bin(u16 gray_code) { - u16 bin = 0, gray_bit; - u32 bit_idx; + u16 binary = gray_code; - for (bit_idx = 0; bit_idx < bit_num; bit_idx++) { - gray_bit = (gray_code >> bit_idx) & 0x1; - if (bit_num - bit_idx > 1) - gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1; - bin |= (gray_bit << bit_idx); + while (gray_code) { + gray_code >>= 1; + binary ^= gray_code; } - return bin; + return binary; } static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev) @@ -3772,7 +3793,7 @@ static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev) val16 = rtw89_read16_mask(rtwdev, phy_offset + RAC_ANA1F * RAC_MULT, FILTER_OUT_EQ_MASK); - val16 = gray_code_to_bin(val16, hweight16(val16)); + val16 = gray_code_to_bin(val16); filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 * RAC_MULT); filter_out_val &= ~REG_FILTER_OUT_MASK; @@ -4188,6 +4209,17 @@ static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev) RTW89_PCIE_BIT_CFG_RST_MSTATE); } +void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume) +{ + if (resume) + rtw89_pci_cfg_dac(rtwdev); + + rtw89_pci_disable_eq(rtwdev); + rtw89_pci_filter_out(rtwdev); + rtw89_pci_link_cfg(rtwdev); + rtw89_pci_l1ss_cfg(rtwdev); +} + static int __maybe_unused rtw89_pci_resume(struct device *dev) { struct ieee80211_hw *hw = dev_get_drvdata(dev); @@ -4209,11 +4241,8 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev) B_AX_SEL_REQ_ENTR_L1); } rtw89_pci_l2_hci_ldo(rtwdev); - rtw89_pci_disable_eq(rtwdev); - rtw89_pci_cfg_dac(rtwdev); - rtw89_pci_filter_out(rtwdev); - rtw89_pci_link_cfg(rtwdev); - rtw89_pci_l1ss_cfg(rtwdev); + + rtw89_pci_basic_cfg(rtwdev, true); return 0; } @@ -4246,6 +4275,8 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { .aspm_set = rtw89_pci_aspm_set_ax, .clkreq_set = rtw89_pci_clkreq_set_ax, .l1ss_set = rtw89_pci_l1ss_set_ax, + + .disable_eq = rtw89_pci_disable_eq_ax, }; EXPORT_SYMBOL(rtw89_pci_gen_ax); @@ -4345,10 +4376,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_clear_resource; } - rtw89_pci_disable_eq(rtwdev); - rtw89_pci_filter_out(rtwdev); - rtw89_pci_link_cfg(rtwdev); - rtw89_pci_l1ss_cfg(rtwdev); + rtw89_pci_basic_cfg(rtwdev, false); ret = rtw89_core_napi_init(rtwdev); if (ret) { diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 48c3ab735db2..796f6cd3c965 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -18,11 +18,16 @@ #define BAC_OOBS_SEL BIT(4) #define RAC_ANA0A 0x0A #define B_BAC_EQ_SEL BIT(5) +#define RAC_ANA0B 0x0B +#define MANUAL_LVL_MASK GENMASK(8, 5) #define RAC_ANA0C 0x0C #define B_PCIE_BIT_PSAVE BIT(15) #define RAC_ANA0D 0x0D +#define OFFSET_CAL_MODE BIT(13) #define BAC_RX_TEST_EN BIT(6) #define RAC_ANA10 0x10 +#define ADDR_SEL_MASK GENMASK(9, 4) +#define ADDR_SEL_VAL 0x3C #define ADDR_SEL_PINOUT_DIS_VAL 0x3C4 #define B_PCIE_BIT_PINOUT_DIS BIT(3) #define RAC_REG_REV2 0x1B @@ -38,6 +43,7 @@ #define RAC_ANA1E_G2_VAL 0x6EEA #define RAC_ANA1F 0x1F #define OOBS_LEVEL_MASK GENMASK(12, 8) +#define OFFSET_CAL_MASK GENMASK(7, 4) #define RAC_ANA24 0x24 #define B_AX_DEGLITCH GENMASK(11, 8) #define RAC_ANA26 0x26 @@ -134,6 +140,11 @@ #define REG_FILTER_OUT_MASK GENMASK(6, 2) #define RAC_MULT 2 +#define R_RAC_DIRECT_OFFSET_BE_LANE0_G1 0x3800 +#define R_RAC_DIRECT_OFFSET_BE_LANE1_G1 0x3880 +#define R_RAC_DIRECT_OFFSET_BE_LANE0_G2 0x3900 +#define R_RAC_DIRECT_OFFSET_BE_LANE1_G2 0x3980 + #define RTW89_PCI_WR_RETRY_CNT 20 /* Interrupts */ @@ -299,6 +310,7 @@ #define B_BE_L1SS_TIMEOUT_CTRL BIT(18) #define B_BE_ASPM_CTRL_L1 BIT(17) #define B_BE_ASPM_CTRL_L0 BIT(16) +#define B_BE_RTK_ASPM_CTRL_MASK GENMASK(17, 16) #define B_BE_XFER_PENDING_FW BIT(11) #define B_BE_XFER_PENDING BIT(10) #define B_BE_REQ_EXIT_L1 BIT(9) @@ -1276,6 +1288,8 @@ struct rtw89_pci_gen_def { void (*aspm_set)(struct rtw89_dev *rtwdev, bool enable); void (*clkreq_set)(struct rtw89_dev *rtwdev, bool enable); void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable); + + void (*disable_eq)(struct rtw89_dev *rtwdev); }; struct rtw89_pci_info { @@ -1600,6 +1614,7 @@ struct pci_device_id; int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); void rtw89_pci_remove(struct pci_dev *pdev); +void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume); void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev); int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en); int rtw89_pci_ltr_set_v1(struct rtw89_dev *rtwdev, bool en); @@ -1766,4 +1781,13 @@ static inline int rtw89_pci_poll_txdma_ch_idle(struct rtw89_dev *rtwdev) return gen_def->poll_txdma_ch_idle(rtwdev); } + +static inline void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) +{ + const struct rtw89_pci_info *info = rtwdev->pci_info; + const struct rtw89_pci_gen_def *gen_def = info->gen_def; + + gen_def->disable_eq(rtwdev); +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c index 7cc328222965..34154506f5d4 100644 --- a/drivers/net/wireless/realtek/rtw89/pci_be.c +++ b/drivers/net/wireless/realtek/rtw89/pci_be.c @@ -550,6 +550,79 @@ static int rtw89_pci_lv1rst_start_dma_be(struct rtw89_dev *rtwdev) return 0; } +static void rtw89_pci_disable_eq_be(struct rtw89_dev *rtwdev) +{ + u32 backup_aspm, phy_offset; + u16 oobs_val, offset_cal; + u16 g1_oobs, g2_oobs; + u8 gen; + + if (rtwdev->chip->chip_id != RTL8922A) + return; + + g1_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + g2_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G2 + + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + if (g1_oobs && g2_oobs) + return; + + backup_aspm = rtw89_read32(rtwdev, R_BE_PCIE_MIX_CFG); + rtw89_write32_clr(rtwdev, R_BE_PCIE_MIX_CFG, B_BE_RTK_ASPM_CTRL_MASK); + + /* offset K */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT, + MANUAL_LVL_MASK, offset_cal); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + OFFSET_CAL_MODE); + } + + /* OOBS */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + BAC_RX_TEST_EN); + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, + ADDR_SEL_MASK, ADDR_SEL_VAL); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, + B_PCIE_BIT_PINOUT_DIS); + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + oobs_val = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA1F * RAC_MULT, OOBS_LEVEL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA03 * RAC_MULT, + OOBS_SEN_MASK, oobs_val); + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA09 * RAC_MULT, + BAC_OOBS_SEL); + } + + rtw89_write32(rtwdev, R_BE_PCIE_MIX_CFG, backup_aspm); +} + static int __maybe_unused rtw89_pci_suspend_be(struct device *dev) { struct ieee80211_hw *hw = dev_get_drvdata(dev); @@ -584,6 +657,8 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev) rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR); + rtw89_pci_basic_cfg(rtwdev, true); + return 0; } @@ -614,5 +689,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_be = { .aspm_set = rtw89_pci_aspm_set_be, .clkreq_set = rtw89_pci_clkreq_set_be, .l1ss_set = rtw89_pci_l1ss_set_be, + + .disable_eq = rtw89_pci_disable_eq_be, }; EXPORT_SYMBOL(rtw89_pci_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index c7165e757842..5a08e3d46bac 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -75,12 +75,12 @@ static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap) return ra_mask; } -static u64 get_he_ra_mask(struct ieee80211_sta *sta) +static u64 get_he_ra_mask(struct ieee80211_link_sta *link_sta) { - struct ieee80211_sta_he_cap cap = sta->deflink.he_cap; + struct ieee80211_sta_he_cap cap = link_sta->he_cap; u16 mcs_map; - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: if (cap.he_cap_elem.phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) @@ -118,14 +118,14 @@ static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss) return mask; } -static u64 get_eht_ra_mask(struct ieee80211_sta *sta) +static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta) { - struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; - u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_320: mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320; /* MCS 9, 11, 13 */ @@ -195,15 +195,16 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak) return ra_mask; } -static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, const struct rtw89_chan *chan) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); - struct cfg80211_bitrate_mask *mask = &rtwsta->mask; + struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; enum nl80211_band band; u64 cfg_mask; - if (!rtwsta->use_cfg_mask) + if (!rtwsta_link->use_cfg_mask) return -1; switch (chan->band_type) { @@ -227,17 +228,17 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw return -1; } - if (sta->deflink.he_cap.has_he) { + if (link_sta->he_cap.has_he) { cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0], RA_MASK_HE_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1], RA_MASK_HE_2SS_RATES); - } else if (sta->deflink.vht_cap.vht_supported) { + } else if (link_sta->vht_cap.vht_supported) { cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0], RA_MASK_VHT_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1], RA_MASK_VHT_2SS_RATES); - } else if (sta->deflink.ht_cap.ht_supported) { + } else if (link_sta->ht_cap.ht_supported) { cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0], RA_MASK_HT_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1], @@ -261,17 +262,17 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES, RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES}; static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, const struct rtw89_chan *chan, bool *fix_giltf_en, u8 *fix_giltf) { - struct cfg80211_bitrate_mask *mask = &rtwsta->mask; + struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); u8 he_gi = mask->control[nl_band].he_gi; u8 he_ltf = mask->control[nl_band].he_ltf; - if (!rtwsta->use_cfg_mask) + if (!rtwsta_link->use_cfg_mask) return; if (he_ltf == 2 && he_gi == 2) { @@ -295,17 +296,17 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, } static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool csi) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, + bool p2p, bool csi) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; - struct rtw89_ra_info *ra = &rtwsta->ra; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + struct rtw89_ra_info *ra = &rtwsta_link->ra; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); + rtwvif_link->chanctx_idx); const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; - u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); u64 ra_mask = 0; u64 ra_mask_bak; u8 mode = 0; @@ -320,65 +321,65 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, memset(ra, 0, sizeof(*ra)); /* Set the ra mask from sta's capability */ - if (sta->deflink.eht_cap.has_eht) { + if (link_sta->eht_cap.has_eht) { mode |= RTW89_RA_MODE_EHT; - ra_mask |= get_eht_ra_mask(sta); + ra_mask |= get_eht_ra_mask(link_sta); high_rate_masks = rtw89_ra_mask_eht_rates; - } else if (sta->deflink.he_cap.has_he) { + } else if (link_sta->he_cap.has_he) { mode |= RTW89_RA_MODE_HE; csi_mode = RTW89_RA_RPT_MODE_HE; - ra_mask |= get_he_ra_mask(sta); + ra_mask |= get_he_ra_mask(link_sta); high_rate_masks = rtw89_ra_mask_he_rates; - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[2] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[2] & IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) stbc_en = 1; - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) ldpc_en = 1; - rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf); - } else if (sta->deflink.vht_cap.vht_supported) { - u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf); + } else if (link_sta->vht_cap.vht_supported) { + u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map); mode |= RTW89_RA_MODE_VHT; csi_mode = RTW89_RA_RPT_MODE_VHT; /* MCS9 (non-20MHz), MCS8, MCS7 */ - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) ra_mask |= get_mcs_ra_mask(mcs_map, 8, 1); else ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1); high_rate_masks = rtw89_ra_mask_vht_rates; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) stbc_en = 1; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) ldpc_en = 1; - } else if (sta->deflink.ht_cap.ht_supported) { + } else if (link_sta->ht_cap.ht_supported) { mode |= RTW89_RA_MODE_HT; csi_mode = RTW89_RA_RPT_MODE_HT; - ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12); + ra_mask |= ((u64)link_sta->ht_cap.mcs.rx_mask[3] << 48) | + ((u64)link_sta->ht_cap.mcs.rx_mask[2] << 36) | + ((u64)link_sta->ht_cap.mcs.rx_mask[1] << 24) | + ((u64)link_sta->ht_cap.mcs.rx_mask[0] << 12); high_rate_masks = rtw89_ra_mask_ht_rates; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) stbc_en = 1; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) ldpc_en = 1; } switch (chan->band_type) { case RTW89_BAND_2G: - ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ]; - if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xf) + ra_mask |= link_sta->supp_rates[NL80211_BAND_2GHZ]; + if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xf) mode |= RTW89_RA_MODE_CCK; - if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xff0) + if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xff0) mode |= RTW89_RA_MODE_OFDM; break; case RTW89_BAND_5G: - ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; + ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_5GHZ] << 4; mode |= RTW89_RA_MODE_OFDM; break; case RTW89_BAND_6G: - ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_6GHZ] << 4; + ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_6GHZ] << 4; mode |= RTW89_RA_MODE_OFDM; break; default: @@ -405,48 +406,48 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0); ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak); - ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); + ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: bw_mode = RTW89_CHANNEL_WIDTH_160; - sgi = sta->deflink.vht_cap.vht_supported && - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); + sgi = link_sta->vht_cap.vht_supported && + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); break; case IEEE80211_STA_RX_BW_80: bw_mode = RTW89_CHANNEL_WIDTH_80; - sgi = sta->deflink.vht_cap.vht_supported && - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + sgi = link_sta->vht_cap.vht_supported && + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); break; case IEEE80211_STA_RX_BW_40: bw_mode = RTW89_CHANNEL_WIDTH_40; - sgi = sta->deflink.ht_cap.ht_supported && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40); + sgi = link_sta->ht_cap.ht_supported && + (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); break; default: bw_mode = RTW89_CHANNEL_WIDTH_20; - sgi = sta->deflink.ht_cap.ht_supported && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20); + sgi = link_sta->ht_cap.ht_supported && + (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); break; } - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM) ra->dcm_cap = 1; - if (rate_pattern->enable && !vif->p2p) { - ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); + if (rate_pattern->enable && !p2p) { + ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); ra_mask &= rate_pattern->ra_mask; mode = rate_pattern->ra_mode; } ra->bw_cap = bw_mode; - ra->er_cap = rtwsta->er_cap; + ra->er_cap = rtwsta_link->er_cap; ra->mode_ctrl = mode; - ra->macid = rtwsta->mac_id; + ra->macid = rtwsta_link->mac_id; ra->stbc_cap = stbc_en; ra->ldpc_cap = ldpc_en; - ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; + ra->ss_num = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; ra->en_sgi = sgi; ra->ra_mask = ra_mask; ra->fix_giltf_en = fix_giltf_en; @@ -458,20 +459,29 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->fixed_csi_rate_en = false; ra->ra_csi_rate_en = true; ra->cr_tbl_sel = false; - ra->band_num = rtwvif->phy_idx; + ra->band_num = rtwvif_link->phy_idx; ra->csi_bw = bw_mode; ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32; ra->csi_mcs_ss_idx = 5; ra->csi_mode = csi_mode; } -void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, - u32 changed) +static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + u32 changed) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_ra_info *ra = &rtwsta->ra; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, + link_sta, vif->p2p, false); - rtw89_phy_ra_sta_update(rtwdev, sta, false); + rcu_read_unlock(); if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) ra->upd_mask = 1; @@ -489,6 +499,20 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta rtw89_fw_h2c_ra(rtwdev, ra, false); } +void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed); + } +} + static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, u16 rate_base, u64 ra_mask, u8 ra_mode, u32 rate_ctrl, u32 ctrl_skip, bool force) @@ -523,15 +547,15 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, [RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \ } -void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask) +static +void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + const struct cfg80211_bitrate_mask *mask) { struct ieee80211_supported_band *sband; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_phy_rate_pattern next_pattern = {0}; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), @@ -600,7 +624,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, if (!next_pattern.enable) goto out; - rtwvif->rate_pattern = next_pattern; + rtwvif_link->rate_pattern = next_pattern; rtw89_debug(rtwdev, RTW89_DBG_RA, "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", next_pattern.rate, @@ -609,10 +633,22 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, return; out: - rtwvif->rate_pattern.enable = false; + rtwvif_link->rate_pattern.enable = false; rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n"); } +void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + __rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask); +} + static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; @@ -627,14 +663,24 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) rtwdev); } -void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) +void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_ra_info *ra = &rtwsta->ra; - u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; - bool csi = rtw89_sta_has_beamformer_cap(sta); + struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; + struct ieee80211_link_sta *link_sta; + bool csi; - rtw89_phy_ra_sta_update(rtwdev, sta, csi); + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + csi = rtw89_sta_has_beamformer_cap(link_sta); + + rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, + link_sta, vif->p2p, csi); + + rcu_read_unlock(); if (rssi > 40) ra->init_rate_lv = 1; @@ -1068,14 +1114,21 @@ static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev) return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1; } -static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) +static void __rtw89_phy_bb_reset(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; chip->ops->bb_reset(rtwdev, phy_idx); } +static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev) +{ + __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_1); +} + static void rtw89_phy_config_bb_reg(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, @@ -1621,13 +1674,15 @@ void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev) if (rtwdev->dbcc_en) rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg, (void *)RTW89_PHY_1); - rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + + rtw89_chip_init_txpwr_unit(rtwdev); bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table; if (bb_gain_table) rtw89_phy_init_reg(rtwdev, bb_gain_table, chip->phy_def->config_bb_gain, NULL); - rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0); + + rtw89_phy_bb_reset(rtwdev); } static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev) @@ -1747,6 +1802,24 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, } EXPORT_SYMBOL(rtw89_phy_write32_idx); +void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx) +{ + if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1) + addr += rtw89_phy0_phy1_offset(rtwdev, addr); + rtw89_phy_write32_set(rtwdev, addr, bits); +} +EXPORT_SYMBOL(rtw89_phy_write32_idx_set); + +void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx) +{ + if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1) + addr += rtw89_phy0_phy1_offset(rtwdev, addr); + rtw89_phy_write32_clr(rtwdev, addr, bits); +} +EXPORT_SYMBOL(rtw89_phy_write32_idx_clr); + u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, enum rtw89_phy_idx phy_idx) { @@ -2553,14 +2626,14 @@ struct rtw89_phy_iter_ra_data { struct sk_buff *c2h; }; -static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, + struct rtw89_phy_iter_ra_data *ra_data) { - struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; struct rtw89_dev *rtwdev = ra_data->rtwdev; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; const struct rtw89_c2h_ra_rpt *c2h = (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; - struct rtw89_ra_report *ra_report = &rtwsta->ra_report; + struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report; const struct rtw89_chip_info *chip = rtwdev->chip; bool format_v1 = chip->chip_gen == RTW89_CHIP_BE; u8 mode, rate, bw, giltf, mac_id; @@ -2570,7 +2643,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) u8 t; mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); - if (mac_id != rtwsta->mac_id) + if (mac_id != rtwsta_link->mac_id) return; rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS); @@ -2661,8 +2734,26 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) | u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); ra_report->might_fallback_legacy = mcs <= 2; - sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); - rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; + link_sta->agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); + rtwsta_link->max_agg_wait = link_sta->agg.max_rc_amsdu_len / 1500 - 1; +} + +static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + struct ieee80211_link_sta *link_sta; + unsigned int link_id; + + rcu_read_lock(); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data); + } + + rcu_read_unlock(); } static void @@ -2692,9 +2783,85 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, struct rtw89_c2h_rf_txgapk_rpt_log *txgapk; struct rtw89_c2h_rf_rxdck_rpt_log *rxdck; struct rtw89_c2h_rf_dack_rpt_log *dack; + struct rtw89_c2h_rf_tssi_rpt_log *tssi; struct rtw89_c2h_rf_dpk_rpt_log *dpk; + struct rtw89_c2h_rf_iqk_rpt_log *iqk; + int i, j, k; switch (func) { + case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK: + if (len != sizeof(*iqk)) + goto out; + + iqk = content; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_iqk_init = %x\n", iqk->is_iqk_init); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_reload = %x\n", iqk->is_reload); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_nbiqk = %x\n", iqk->is_nbiqk); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->txiqk_en = %x\n", iqk->txiqk_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rxiqk_en = %x\n", iqk->rxiqk_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->lok_en = %x\n", iqk->lok_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_xym_en = %x\n", iqk->iqk_xym_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_sram_en = %x\n", iqk->iqk_sram_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_fft_en = %x\n", iqk->iqk_fft_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_fw_iqk = %x\n", iqk->is_fw_iqk); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_iqk_enable = %x\n", iqk->is_iqk_enable); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_cfir_en = %x\n", iqk->iqk_cfir_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->thermal_rek_en = %x\n", iqk->thermal_rek_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->version = %x\n", iqk->version); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->phy = %x\n", iqk->phy); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->fwk_status = %x\n", iqk->fwk_status); + + for (i = 0; i < 2; i++) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] ======== Path %x ========\n", i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_band[%d] = %x\n", + i, iqk->iqk_band[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_ch[%d] = %x\n", + i, iqk->iqk_ch[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n", + i, iqk->iqk_bw[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n", + i, le32_to_cpu(iqk->lok_idac[i])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n", + i, le32_to_cpu(iqk->lok_vbuf[i])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_tx_fail[%d] = %x\n", + i, iqk->iqk_tx_fail[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n", + i, iqk->iqk_rx_fail[i]); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rftxgain[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rftxgain[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->tx_xym[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->tx_xym[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rfrxgain[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rfrxgain[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rx_xym[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rx_xym[i][j])); + } + return; case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK: if (len != sizeof(*dpk)) goto out; @@ -2716,8 +2883,23 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack = content; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ver=0x%x 0x%x\n", - dack->fwdack_ver, dack->fwdack_rpt_ver); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]FWDACK SUMMARY!!!!!\n"); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]FWDACK ver = 0x%x, FWDACK rpt_ver = 0x%x, driver rpt_ver = 0x%x\n", + dack->fwdack_ver, dack->fwdack_info_ver, 0x2); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]timeout code = [0x%x 0x%x 0x%x 0x%x 0x%x]\n", + dack->addck_timeout, dack->cdack_timeout, dack->dadck_timeout, + dack->adgaink_timeout, dack->msbk_timeout); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]DACK fail = 0x%x\n", dack->dack_fail); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]S0 WBADCK = [0x%x]\n", dack->wbdck_d[0]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]S1 WBADCK = [0x%x]\n", dack->wbdck_d[1]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]DRCK = [0x%x]\n", dack->rck_d); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK ic = [0x%x, 0x%x]\n", dack->cdack_d[0][0][0], dack->cdack_d[0][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK qc = [0x%x, 0x%x]\n", @@ -2728,13 +2910,17 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack->cdack_d[1][1][0], dack->cdack_d[1][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = [0x%x, 0x%x]\n", - dack->addck2_d[0][0][0], dack->addck2_d[0][0][1]); + ((u32)dack->addck2_hd[0][0][0] << 8) | dack->addck2_ld[0][0][0], + ((u32)dack->addck2_hd[0][0][1] << 8) | dack->addck2_ld[0][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK qc = [0x%x, 0x%x]\n", - dack->addck2_d[0][1][0], dack->addck2_d[0][1][1]); + ((u32)dack->addck2_hd[0][1][0] << 8) | dack->addck2_ld[0][1][0], + ((u32)dack->addck2_hd[0][1][1] << 8) | dack->addck2_ld[0][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK ic = [0x%x, 0x%x]\n", - dack->addck2_d[1][0][0], dack->addck2_d[1][0][1]); + ((u32)dack->addck2_hd[1][0][0] << 8) | dack->addck2_ld[1][0][0], + ((u32)dack->addck2_hd[1][0][1] << 8) | dack->addck2_ld[1][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK qc = [0x%x, 0x%x]\n", - dack->addck2_d[1][1][0], dack->addck2_d[1][1][1]); + ((u32)dack->addck2_hd[1][1][0] << 8) | dack->addck2_ld[1][1][0], + ((u32)dack->addck2_hd[1][1][1] << 8) | dack->addck2_ld[1][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_GAINK ic = 0x%x, qc = 0x%x\n", dack->adgaink_d[0][0], dack->adgaink_d[0][1]); @@ -2747,18 +2933,29 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack->dadck_d[1][0], dack->dadck_d[1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask iqc = 0x%x\n", - dack->biask_d[0][0]); + ((u32)dack->biask_hd[0][0] << 8) | dack->biask_ld[0][0]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 biask iqc = 0x%x\n", - dack->biask_d[1][0]); - - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic: %*ph\n", - (int)sizeof(dack->msbk_d[0][0]), dack->msbk_d[0][0]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc: %*ph\n", - (int)sizeof(dack->msbk_d[0][1]), dack->msbk_d[0][1]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic: %*ph\n", - (int)sizeof(dack->msbk_d[1][0]), dack->msbk_d[1][0]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc: %*ph\n", - (int)sizeof(dack->msbk_d[1][1]), dack->msbk_d[1][1]); + ((u32)dack->biask_hd[1][0] << 8) | dack->biask_ld[1][0]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[0][0][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[0][1][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[1][0][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[1][1][i]); return; case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK: if (len != sizeof(*rxdck)) @@ -2770,6 +2967,39 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, rxdck->ver, rxdck->band, rxdck->bw, rxdck->ch, rxdck->timeout); return; + case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI: + if (len != sizeof(*tssi)) + goto out; + + tssi = content; + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 4; k++) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw_h[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power_cw_h[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw_l[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power_cw_l[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw[%d][%d][%d]=%d\n", + i, j, k, + (tssi->alignment_power_cw_h[i][j][k] << 8) + + tssi->alignment_power_cw_l[i][j][k]); + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] tssi_alimk_state[%d][%d]=%d\n", + i, j, tssi->tssi_alimk_state[i][j]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] default_txagc_offset[%d]=%d\n", + j, tssi->default_txagc_offset[0][j]); + } + } + return; case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK: if (len != sizeof(*txgapk)) goto out; @@ -3171,13 +3401,13 @@ EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait); int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, - unsigned int ms) + bool is_chl_k, unsigned int ms) { int ret; rtw89_phy_rfk_report_prep(rtwdev); - ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan); + ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan, is_chl_k); if (ret) return ret; @@ -4290,33 +4520,33 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val, cfo->packet_count++; } -void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info; if (!chip->ul_tb_waveform_ctrl) return; - rtwvif->def_tri_idx = + rtwvif_link->def_tri_idx = rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG); if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV) - rtwvif->dyn_tb_bedge_en = false; + rtwvif_link->dyn_tb_bedge_en = false; else if (chan->band_type >= RTW89_BAND_5G && chan->band_width >= RTW89_CHANNEL_WIDTH_40) - rtwvif->dyn_tb_bedge_en = true; + rtwvif_link->dyn_tb_bedge_en = true; else - rtwvif->dyn_tb_bedge_en = false; + rtwvif_link->dyn_tb_bedge_en = false; rtw89_debug(rtwdev, RTW89_DBG_UL_TB, "[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n", - ul_tb_info->def_if_bandedge, rtwvif->def_tri_idx); + ul_tb_info->def_if_bandedge, rtwvif_link->def_tri_idx); rtw89_debug(rtwdev, RTW89_DBG_UL_TB, "[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n", - rtwvif->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); + rtwvif_link->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); } struct rtw89_phy_ul_tb_check_data { @@ -4338,7 +4568,7 @@ struct rtw89_phy_power_diff { }; static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { static const struct rtw89_phy_power_diff table[2] = { {0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3}, @@ -4350,13 +4580,13 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, if (!rtwdev->chip->ul_tb_pwr_diff) return; - if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) { - rtwvif->pwr_diff_en = false; + if (rtwvif_link->pwr_diff_en == rtwvif_link->pre_pwr_diff_en) { + rtwvif_link->pwr_diff_en = false; return; } - rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en; - param = &table[rtwvif->pwr_diff_en]; + rtwvif_link->pre_pwr_diff_en = rtwvif_link->pwr_diff_en; + param = &table[rtwvif_link->pwr_diff_en]; rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL, param->q_00); @@ -4365,32 +4595,32 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX, B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160, param->ultb_1t_norm_160); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160, param->ultb_2t_norm_160); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS, param->com1_norm_1sts); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH, param->com2_resp_1sts_path); } static void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_phy_ul_tb_check_data *ul_tb_data) { struct rtw89_traffic_stats *stats = &rtwdev->stats; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) return; if (!vif->cfg.assoc) @@ -4403,11 +4633,11 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, ul_tb_data->low_tf_client = true; ul_tb_data->valid = true; - ul_tb_data->def_tri_idx = rtwvif->def_tri_idx; - ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en; + ul_tb_data->def_tri_idx = rtwvif_link->def_tri_idx; + ul_tb_data->dyn_tb_bedge_en = rtwvif_link->dyn_tb_bedge_en; } - rtw89_phy_ofdma_power_diff(rtwdev, rtwvif); + rtw89_phy_ofdma_power_diff(rtwdev, rtwvif_link); } static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev, @@ -4453,7 +4683,9 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_phy_ul_tb_check_data ul_tb_data = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff) return; @@ -4462,7 +4694,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif, &ul_tb_data); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data); if (!ul_tb_data.valid) return; @@ -4626,30 +4859,42 @@ struct rtw89_phy_iter_rssi_data { bool rssi_changed; }; -static void rtw89_phy_stat_rssi_update_iter(void *data, - struct ieee80211_sta *sta) +static +void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link, + struct rtw89_phy_iter_rssi_data *rssi_data) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_phy_iter_rssi_data *rssi_data = - (struct rtw89_phy_iter_rssi_data *)data; struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info; unsigned long rssi_curr; - rssi_curr = ewma_rssi_read(&rtwsta->avg_rssi); + rssi_curr = ewma_rssi_read(&rtwsta_link->avg_rssi); if (rssi_curr < ch_info->rssi_min) { ch_info->rssi_min = rssi_curr; - ch_info->rssi_min_macid = rtwsta->mac_id; + ch_info->rssi_min_macid = rtwsta_link->mac_id; } - if (rtwsta->prev_rssi == 0) { - rtwsta->prev_rssi = rssi_curr; - } else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) { - rtwsta->prev_rssi = rssi_curr; + if (rtwsta_link->prev_rssi == 0) { + rtwsta_link->prev_rssi = rssi_curr; + } else if (abs((int)rtwsta_link->prev_rssi - (int)rssi_curr) > + (3 << RSSI_FACTOR)) { + rtwsta_link->prev_rssi = rssi_curr; rssi_data->rssi_changed = true; } } +static void rtw89_phy_stat_rssi_update_iter(void *data, + struct ieee80211_sta *sta) +{ + struct rtw89_phy_iter_rssi_data *rssi_data = + (struct rtw89_phy_iter_rssi_data *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + __rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data); +} + static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev) { struct rtw89_phy_iter_rssi_data rssi_data = {0}; @@ -4676,6 +4921,8 @@ static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev) memset(&phystat->cur_pkt_stat, 0, sizeof(phystat->cur_pkt_stat)); memset(&phystat->last_pkt_stat, 0, sizeof(phystat->last_pkt_stat)); + + ewma_rssi_init(&phystat->bcn_rssi); } void rtw89_phy_stat_track(struct rtw89_dev *rtwdev) @@ -5188,7 +5435,8 @@ static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page) } static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, - enum rtw89_phy_status_bitmap ie_page) + enum rtw89_phy_status_bitmap ie_page, + enum rtw89_phy_idx phy_idx) { u32 addr; @@ -5197,12 +5445,12 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, addr = rtw89_phy_get_ie_bitmap_addr(ie_page); - return rtw89_phy_read32(rtwdev, addr); + return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx); } static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, enum rtw89_phy_status_bitmap ie_page, - u32 val) + u32 val, enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; u32 addr; @@ -5214,22 +5462,22 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, val &= B_PHY_STS_BITMAP_MSK_52A; addr = rtw89_phy_get_ie_bitmap_addr(ie_page); - rtw89_phy_write32(rtwdev, addr, val); + rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx); } static void rtw89_physts_enable_ie_bitmap(struct rtw89_dev *rtwdev, enum rtw89_phy_status_bitmap bitmap, enum rtw89_phy_status_ie_type ie, - bool enable) + bool enable, enum rtw89_phy_idx phy_idx) { - u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap); + u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap, phy_idx); if (enable) val |= BIT(ie); else val &= ~BIT(ie); - rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val); + rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val, phy_idx); } static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, @@ -5240,44 +5488,52 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, const struct rtw89_physts_regs *physts = phy->physts; if (enable) { - rtw89_phy_write32_clr(rtwdev, physts->setting_addr, - physts->dis_trigger_fail_mask); - rtw89_phy_write32_clr(rtwdev, physts->setting_addr, - physts->dis_trigger_brk_mask); + rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask, phy_idx); + rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask, phy_idx); } else { - rtw89_phy_write32_set(rtwdev, physts->setting_addr, - physts->dis_trigger_fail_mask); - rtw89_phy_write32_set(rtwdev, physts->setting_addr, - physts->dis_trigger_brk_mask); + rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask, phy_idx); + rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask, phy_idx); } } -static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev) +static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { u8 i; - rtw89_physts_enable_fail_report(rtwdev, false, RTW89_PHY_0); + rtw89_physts_enable_fail_report(rtwdev, false, phy_idx); for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) { if (i >= RTW89_CCK_PKT) rtw89_physts_enable_ie_bitmap(rtwdev, i, RTW89_PHYSTS_IE09_FTR_0, - true); + true, phy_idx); if ((i >= RTW89_CCK_BRK && i <= RTW89_VHT_MU) || (i >= RTW89_RSVD_9 && i <= RTW89_CCK_PKT)) continue; rtw89_physts_enable_ie_bitmap(rtwdev, i, RTW89_PHYSTS_IE24_OFDM_TD_PATH_A, - true); + true, phy_idx); } rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_VHT_PKT, - RTW89_PHYSTS_IE13_DL_MU_DEF, true); + RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx); rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_HE_PKT, - RTW89_PHYSTS_IE13_DL_MU_DEF, true); + RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx); /* force IE01 for channel index, only channel field is valid */ rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_CCK_PKT, - RTW89_PHYSTS_IE01_CMN_OFDM, true); + RTW89_PHYSTS_IE01_CMN_OFDM, true, phy_idx); +} + +static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev) +{ + __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_1); } static void rtw89_phy_dig_read_gain_table(struct rtw89_dev *rtwdev, int type) @@ -5753,26 +6009,15 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev) rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false); } -static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_hal *hal = &rtwdev->hal; - bool *done = data; u8 rssi_a, rssi_b; u32 candidate; - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls) - return; - - if (*done) - return; - - *done = true; - - rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]); - rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]); + rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]); + rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]); if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH) candidate = RF_A; @@ -5785,7 +6030,7 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta return; hal->antenna_tx = candidate; - rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta); + rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta_link); if (hal->antenna_tx == RF_A) { rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12); @@ -5796,6 +6041,37 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta } } +static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + bool *done = data; + + if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n")) + return; + + if (sta->tdls) + return; + + if (*done) + return; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) + continue; + + *done = true; + __rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link); + return; + } +} + void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; @@ -6002,17 +6278,27 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_chip_cfg_txrx_path(rtwdev); } -void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld; - enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + struct ieee80211_bss_conf *bss_conf; u8 bss_color; - if (!vif->bss_conf.he_support || !vif->cfg.assoc) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (!bss_conf->he_support || !vif->cfg.assoc) { + rcu_read_unlock(); return; + } + + bss_color = bss_conf->he_bss_color.color; - bss_color = vif->bss_conf.he_bss_color.color; + rcu_read_unlock(); rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1, phy_idx); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 6dd8ec46939a..c683f4d7d29b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -815,6 +815,10 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, void rtw89_phy_dm_init(struct rtw89_dev *rtwdev); void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, enum rtw89_phy_idx phy_idx); +void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx); +void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx); u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, enum rtw89_phy_idx phy_idx); s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev, @@ -892,7 +896,7 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev, phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx); } -void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); +void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, u32 changed); @@ -929,7 +933,7 @@ int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev, int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, - unsigned int ms); + bool is_chl_k, unsigned int ms); void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, const struct rtw89_chan *chan, @@ -953,11 +957,12 @@ void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev); void rtw89_phy_antdiv_work(struct work_struct *work); -void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx, enum rtw89_tssi_bandedge_cfg bandedge_cfg); -void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev); u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band); void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx, diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index 72eda9bbd3ae..37d8f254ae32 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -398,10 +398,9 @@ static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev) } } -static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) +static void __rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) { - enum rtw89_mac_idx mac_idx = RTW89_MAC_0; - rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev); rtw89_phy_bb_wrap_tx_path_by_macid_init(rtwdev); rtw89_phy_bb_wrap_listen_path_en_init(rtwdev); @@ -411,6 +410,13 @@ static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) rtw89_phy_bb_wrap_ul_pwr(rtwdev); } +static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) +{ + __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_0); + if (rtwdev->dbcc_en) + __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_1); +} + static void rtw89_phy_ch_info_init_be(struct rtw89_dev *rtwdev) { rtw89_phy_write32_mask(rtwdev, R_CHINFO_SEG, B_CHINFO_SEG_LEN, 0x0); diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index aebd6404f802..c1c12abc2ea9 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -62,9 +62,9 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_power_mode_change(rtwdev, enter); } -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - if (rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) return; if (!rtwdev->ps_mode) @@ -85,23 +85,25 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) rtw89_ps_power_mode_change(rtwdev, false); } -static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { - .macid = rtwvif->mac_id, + .macid = rtwvif_link->mac_id, .psmode = RTW89_MAC_AX_PS_MODE_LEGACY, .lastrpwm = RTW89_LAST_RPWM_PS, }; rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL); rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); - rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); + rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link); } -static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { - .macid = rtwvif->mac_id, + .macid = rtwvif_link->mac_id, .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE, .lastrpwm = RTW89_LAST_RPWM_ACTIVE, }; @@ -109,7 +111,7 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); rtw89_fw_leave_lps_check(rtwdev, 0); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); - rtw89_chip_digital_pwr_comp(rtwdev, rtwvif->phy_idx); + rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx); } void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) @@ -119,7 +121,7 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); } -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool ps_mode) { lockdep_assert_held(&rtwdev->mutex); @@ -127,23 +129,26 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) return; - __rtw89_enter_lps(rtwdev, rtwvif); + __rtw89_enter_lps(rtwdev, rtwvif_link); if (ps_mode) - __rtw89_enter_ps_mode(rtwdev, rtwvif); + __rtw89_enter_ps_mode(rtwdev, rtwvif_link); } -static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) return; - __rtw89_leave_lps(rtwdev, rtwvif); + __rtw89_leave_lps(rtwdev, rtwvif_link); } void rtw89_leave_lps(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; lockdep_assert_held(&rtwdev->mutex); @@ -153,12 +158,15 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_leave_lps_vif(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_leave_lps_vif(rtwdev, rtwvif_link); } void rtw89_enter_ips(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); @@ -166,14 +174,17 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_vif_deinit(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_vif_deinit(rtwdev, rtwvif_link); rtw89_core_stop(rtwdev); } void rtw89_leave_ips(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; int ret; if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) @@ -186,7 +197,8 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev) rtw89_set_channel(rtwdev); rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_vif_init(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_vif_init(rtwdev, rtwvif_link); clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); } @@ -197,48 +209,50 @@ void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl) rtw89_leave_lps(rtwdev); } -static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, enum rtw89_p2pps_action act) { if (act == RTW89_P2P_ACT_UPDATE || act == RTW89_P2P_ACT_REMOVE) return; if (act == RTW89_P2P_ACT_INIT) - rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, true); else if (act == RTW89_P2P_ACT_TERMINATE) - rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false); } static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; enum rtw89_p2pps_action act; u8 noa_id; - if (rtwvif->last_noa_nr == 0) + if (rtwvif_link->last_noa_nr == 0) return; - for (noa_id = 0; noa_id < rtwvif->last_noa_nr; noa_id++) { - if (noa_id == rtwvif->last_noa_nr - 1) + for (noa_id = 0; noa_id < rtwvif_link->last_noa_nr; noa_id++) { + if (noa_id == rtwvif_link->last_noa_nr - 1) act = RTW89_P2P_ACT_TERMINATE; else act = RTW89_P2P_ACT_REMOVE; - rtw89_tsf32_toggle(rtwdev, rtwvif, act); - rtw89_fw_h2c_p2p_act(rtwdev, vif, NULL, act, noa_id); + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, + NULL, act, noa_id); } } static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct ieee80211_p2p_noa_desc *desc; enum rtw89_p2pps_action act; u8 noa_id; for (noa_id = 0; noa_id < RTW89_P2P_MAX_NOA_NUM; noa_id++) { - desc = &vif->bss_conf.p2p_noa_attr.desc[noa_id]; + desc = &bss_conf->p2p_noa_attr.desc[noa_id]; if (!desc->count || !desc->duration) break; @@ -246,16 +260,19 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, act = RTW89_P2P_ACT_INIT; else act = RTW89_P2P_ACT_UPDATE; - rtw89_tsf32_toggle(rtwdev, rtwvif, act); - rtw89_fw_h2c_p2p_act(rtwdev, vif, desc, act, noa_id); + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, + desc, act, noa_id); } - rtwvif->last_noa_nr = noa_id; + rtwvif_link->last_noa_nr = noa_id; } -void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - rtw89_p2p_disable_all_noa(rtwdev, vif); - rtw89_p2p_update_noa(rtwdev, vif); + rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, bss_conf); + rtw89_p2p_update_noa(rtwdev, rtwvif_link, bss_conf); } void rtw89_recalc_lps(struct rtw89_dev *rtwdev) @@ -265,6 +282,12 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; int count = 0; + /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode() + * to take MLO cases into account before doing the following. + */ + if (rtwdev->support_mlo) + goto disable_lps; + mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) goto disable_lps; @@ -291,9 +314,9 @@ disable_lps: rtwdev->lps_enabled = false; } -void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) +void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; struct rtw89_noa_attr_head *noa_head = &ie->noa_head; @@ -318,10 +341,10 @@ void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) noa_head->oppps_ctwindow = 0; } -void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, +void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, const struct ieee80211_p2p_noa_desc *desc) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; struct rtw89_noa_attr_head *noa_head = &ie->noa_head; @@ -338,9 +361,9 @@ void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, ie->noa_desc[setter->noa_count++] = *desc; } -u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data) +u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; void *tail; diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index 54486e4550b6..cdd712966b09 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -5,21 +5,23 @@ #ifndef __RTW89_PS_H_ #define __RTW89_PS_H_ -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool ps_mode); void rtw89_leave_lps(struct rtw89_dev *rtwdev); void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); -void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf); void rtw89_recalc_lps(struct rtw89_dev *rtwdev); -void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif); -void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, +void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link); +void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, const struct ieee80211_p2p_noa_desc *desc); -u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data); +u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data); static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) { diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index a7720a1f17a7..bb064a086970 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -793,22 +793,26 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) { struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; struct rtw89_reg_6ghz_tpe new = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; bool changed = false; rtw89_for_each_rtwvif(rtwdev, rtwvif) { const struct rtw89_reg_6ghz_tpe *tmp; const struct rtw89_chan *chan; - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - if (chan->band_type != RTW89_BAND_6G) - continue; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; - tmp = &rtwvif->reg_6ghz_tpe; - if (!tmp->valid) - continue; + tmp = &rtwvif_link->reg_6ghz_tpe; + if (!tmp->valid) + continue; - tpe_intersect_constraint(&new, tmp->constraint); + tpe_intersect_constraint(&new, tmp->constraint); + } } if (memcmp(®ulatory->reg_6ghz_tpe, &new, @@ -831,19 +835,24 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) } static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool active, + struct rtw89_vif_link *rtwvif_link, bool active, unsigned int *changed) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe; + struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe; + struct ieee80211_bss_conf *bss_conf; memset(tpe, 0, sizeof(*tpe)); - if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) + if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) goto bottom; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe); + + rcu_read_unlock(); + if (!tpe->valid) goto bottom; @@ -867,20 +876,24 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) const struct rtw89_regd *regd = regulatory->regd; enum rtw89_reg_6ghz_power sel; const struct rtw89_chan *chan; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; int count = 0; u8 index; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - if (chan->band_type != RTW89_BAND_6G) - continue; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; - if (count != 0 && rtwvif->reg_6ghz_power == sel) - continue; + if (count != 0 && rtwvif_link->reg_6ghz_power == sel) + continue; - sel = rtwvif->reg_6ghz_power; - count++; + sel = rtwvif_link->reg_6ghz_power; + count++; + } } if (count != 1) @@ -908,35 +921,41 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) } static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool active, + struct rtw89_vif_link *rtwvif_link, bool active, unsigned int *changed) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); if (active) { - switch (vif->bss_conf.power_type) { + switch (bss_conf->power_type) { case IEEE80211_REG_VLP_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; break; case IEEE80211_REG_LPI_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; break; case IEEE80211_REG_SP_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; break; default: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; break; } } else { - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; } + rcu_read_unlock(); + *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); return 0; } -int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool active) { unsigned int changed = 0; @@ -948,11 +967,11 @@ int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc(). */ - ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed); + ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed); if (ret) return ret; - ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed); + ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed); if (ret) return ret; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 1679bd408ef3..f9766bf30e71 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -1590,10 +1590,11 @@ static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev) rtw8851b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx); @@ -1608,10 +1609,12 @@ static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8851b_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index dde96bd63021..42d369d2e916 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -1350,10 +1350,11 @@ static void rtw8852a_rfk_init(struct rtw89_dev *rtwdev) rtw8852a_rx_dck(rtwdev, RTW89_PHY_0, true, RTW89_CHANCTX_0); } -static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx); rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx); @@ -1368,10 +1369,11 @@ static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852a_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); + rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); } static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 12be52f76427..364aa21cbd44 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -562,10 +562,11 @@ static void rtw8852b_rfk_init(struct rtw89_dev *rtwdev) rtw8852b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx); @@ -580,10 +581,12 @@ static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852b_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8852b_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index 7dfdcb5964e1..dab7e71ec6a1 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -535,10 +535,11 @@ static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev) rtw8852bt_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx); @@ -553,10 +554,12 @@ static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852bt_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8852bt_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 1c6e89ab0f4b..dbe77abb2c48 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1846,10 +1846,11 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev) rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false); } -static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); rtw8852c_rx_dck(rtwdev, phy_idx, false); @@ -1866,10 +1867,11 @@ static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852c_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); + rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); } static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index 211c051c2967..3281ee9d7523 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -2350,7 +2350,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, if (dgain > 0x5fc || dgain < 0x556) { _dpk_one_shot(rtwdev, phy, path, D_SYNC); - dgain = _dpk_dgain_read(rtwdev); + _dpk_dgain_read(rtwdev); } if (agc_cnt == 0) { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 63b1ff2f98ed..58c9721ac3ab 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -13,7 +13,7 @@ #include "rtw8922a_rfk.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 1 +#define RTW8922A_FW_FORMAT_MAX 2 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" @@ -1991,14 +1991,23 @@ static void rtw8922a_rfk_init(struct rtw89_dev *rtwdev) memset(rfk_mcc, 0, sizeof(*rfk_mcc)); } +static void __rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan) +{ + rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5); + + rtw89_phy_rfk_dack_and_wait(rtwdev, phy_idx, chan, 58); + rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 32); +} + static void rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); - rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, RTW89_PHY_0, 5); - - rtw89_phy_rfk_dack_and_wait(rtwdev, RTW89_PHY_0, chan, 58); - rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32); + __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_0, chan); + if (rtwdev->dbcc_en) + __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_1, chan); } static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) @@ -2020,11 +2029,12 @@ static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) } } -static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx); u32 tx_en; @@ -2035,9 +2045,9 @@ static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtw rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5); rtw89_phy_rfk_txgapk_and_wait(rtwdev, phy_idx, chan, 54); rtw89_phy_rfk_iqk_and_wait(rtwdev, phy_idx, chan, 84); - rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 6); + rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 20); rtw89_phy_rfk_dpk_and_wait(rtwdev, phy_idx, chan, 34); - rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32); + rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, true, 32); rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_CHLK, BTC_WRFK_STOP); @@ -2050,7 +2060,8 @@ static void rtw8922a_rfk_band_changed(struct rtw89_dev *rtwdev, rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_SCAN, 6); } -static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { } diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 5fc2faa9ba5a..7b203bb7f151 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -300,37 +300,54 @@ static void drv_resume_rx(struct rtw89_ser *ser) static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); - rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; - rtwvif->trigger = false; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + rtwvif->tdls_peer = 0; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); + rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; + rtwvif_link->trigger = false; + } } static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; if (rtwvif != target_rtwvif) return; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) - rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); - if (sta->tdls) - rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; - INIT_LIST_HEAD(&rtwsta->ba_cam_list); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + 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); + } } static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + ieee80211_iterate_stations_atomic(rtwdev->hw, ser_sta_deinit_cam_iter, rtwvif); - rtw89_cam_deinit(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_cam_deinit(rtwdev, rtwvif_link); bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM); } diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 86e24e07780d..3e81fd974ec1 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -421,7 +421,8 @@ static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_key_info *key_info = &rtw_wow->key_info; - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); bool err = false; rcu_read_lock(); @@ -596,7 +597,8 @@ static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready) static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, u32 cipher, u8 keyidx, u8 *gtk) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_cipher_info *cipher_info; struct ieee80211_key_conf *rekey_conf; struct ieee80211_key_conf *key; @@ -632,11 +634,13 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct rtw89_set_key_info_iter_data data = {.error = false, .rx_ready = rx_ready}; + struct ieee80211_bss_conf *bss_conf; struct ieee80211_key_conf *key; rcu_read_lock(); @@ -669,9 +673,15 @@ static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) return; rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn); - ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid, + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ieee80211_gtk_rekey_notify(wow_vif, bss_conf->bssid, aoac_rpt->eapol_key_replay_count, - GFP_KERNEL); + GFP_ATOMIC); + + rcu_read_unlock(); } static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) @@ -681,27 +691,24 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - __rtw89_enter_ps_mode(rtwdev, rtwvif); + __rtw89_enter_ps_mode(rtwdev, rtwvif_link); } static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) - rtw89_enter_lps(rtwdev, rtwvif, false); + rtw89_enter_lps(rtwdev, rtwvif_link, false); else if (rtw89_wow_no_link(rtwdev)) - rtw89_fw_h2c_fwips(rtwdev, rtwvif, true); + rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true); } static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) { rtw89_leave_lps(rtwdev); @@ -709,7 +716,7 @@ static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) if (enable_wow) rtw89_leave_ips(rtwdev); else - rtw89_fw_h2c_fwips(rtwdev, rtwvif, false); + rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, false); } } @@ -734,6 +741,8 @@ static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable) static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct cfg80211_wowlan_nd_info nd_info; @@ -780,35 +789,34 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) break; default: rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason); - ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, - GFP_KERNEL); + ieee80211_report_wowlan_wakeup(wow_vif, NULL, GFP_KERNEL); return; } - ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, - GFP_KERNEL); + ieee80211_report_wowlan_wakeup(wow_vif, &wakeup, GFP_KERNEL); } -static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); /* Current WoWLAN function support setting of only vif in * infra mode or no link mode. When one suitable vif is found, * stop the iteration. */ - if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) + if (rtw_wow->rtwvif_link || vif->type != NL80211_IFTYPE_STATION) return; - switch (rtwvif->net_type) { + switch (rtwvif_link->net_type) { case RTW89_NET_TYPE_INFRA: if (rtw_wow_has_mgd_features(rtwdev)) - rtw_wow->wow_vif = vif; + rtw_wow->rtwvif_link = rtwvif_link; break; case RTW89_NET_TYPE_NO_LINK: if (rtw_wow->pno_inited) - rtw_wow->wow_vif = vif; + rtw_wow->rtwvif_link = rtwvif_link; break; default: break; @@ -865,7 +873,7 @@ static u16 rtw89_calc_crc(u8 *pdata, int length) return ~crc; } -static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, +static int rtw89_wow_pattern_get_type(struct rtw89_vif_link *rtwvif_link, struct rtw89_wow_cam_info *rtw_pattern, const u8 *pattern, u8 da_mask) { @@ -885,7 +893,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, rtw_pattern->bc = true; else if (is_multicast_ether_addr(da)) rtw_pattern->mc = true; - else if (ether_addr_equal(da, rtwvif->mac_addr) && + else if (ether_addr_equal(da, rtwvif_link->mac_addr) && da_mask == GENMASK(5, 0)) rtw_pattern->uc = true; else if (!da_mask) /*da_mask == 0 mean wildcard*/ @@ -897,7 +905,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, } static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, const struct cfg80211_pkt_pattern *pkt_pattern, struct rtw89_wow_cam_info *rtw_pattern) { @@ -916,7 +924,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, mask_len = DIV_ROUND_UP(len, 8); memset(rtw_pattern, 0, sizeof(*rtw_pattern)); - ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern, + ret = rtw89_wow_pattern_get_type(rtwvif_link, rtw_pattern, pattern, mask[0] & GENMASK(5, 0)); if (ret) return ret; @@ -970,7 +978,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, } static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct cfg80211_wowlan *wowlan) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; @@ -983,7 +991,7 @@ static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, for (i = 0; i < wowlan->n_patterns; i++) { rtw_pattern = &rtw_wow->patterns[i]; - ret = rtw89_wow_pattern_generate(rtwdev, rtwvif, + ret = rtw89_wow_pattern_generate(rtwdev, rtwvif_link, &wowlan->patterns[i], rtw_pattern); if (ret) { @@ -1040,7 +1048,7 @@ static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - rtw_wow->wow_vif = NULL; + rtw_wow->rtwvif_link = NULL; rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM); rtw_wow->pattern_cnt = 0; rtw_wow->pno_inited = false; @@ -1066,6 +1074,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; if (wowlan->disconnect) @@ -1078,36 +1087,40 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, if (wowlan->nd_config) rtw89_wow_init_pno(rtwdev, wowlan->nd_config); - rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_wow_vif_iter(rtwdev, rtwvif); + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + /* use the link on HW-0 to do wow flow */ + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (!rtwvif_link) + continue; + + rtw89_wow_vif_iter(rtwdev, rtwvif_link); + } - if (!rtw_wow->wow_vif) + rtwvif_link = rtw_wow->rtwvif_link; + if (!rtwvif_link) return -EPERM; - rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; - return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan); + return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan); } static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) { - struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int ret; - ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "failed to config pno\n"); return ret; } - ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); return ret; } - ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow global\n"); return ret; @@ -1119,34 +1132,39 @@ static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct ieee80211_sta *wow_sta; - struct rtw89_sta *rtwsta = NULL; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_sta *rtwsta; int ret; - wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); - if (wow_sta) - rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); + if (wow_sta) { + rtwsta = sta_to_rtwsta(wow_sta); + rtwsta_link = rtwsta->links[rtwvif_link->link_id]; + if (!rtwsta_link) + return -ENOLINK; + } if (wow) { if (rtw_wow->pattern_cnt) - rtwvif->wowlan_pattern = true; + rtwvif_link->wowlan_pattern = true; if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) - rtwvif->wowlan_magic = true; + rtwvif_link->wowlan_magic = true; } else { - rtwvif->wowlan_pattern = false; - rtwvif->wowlan_magic = false; + rtwvif_link->wowlan_pattern = false; + rtwvif_link->wowlan_magic = false; } - ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); return ret; } if (wow) { - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", ret); @@ -1154,13 +1172,13 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) } } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } - ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow global\n"); return ret; @@ -1190,25 +1208,30 @@ 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; enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; const struct rtw89_chip_info *chip = rtwdev->chip; bool include_bb = !!chip->bbmcu_nr; bool disable_intr_for_dlfw = false; struct ieee80211_sta *wow_sta; - struct rtw89_sta *rtwsta = NULL; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_sta *rtwsta; bool is_conn = true; int ret; if (chip_id == RTL8852C || chip_id == RTL8922A) disable_intr_for_dlfw = true; - wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); - if (wow_sta) - rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; - else + wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); + if (wow_sta) { + rtwsta = sta_to_rtwsta(wow_sta); + rtwsta_link = rtwsta->links[rtwvif_link->link_id]; + if (!rtwsta_link) + return -ENOLINK; + } else { is_conn = false; + } if (disable_intr_for_dlfw) rtw89_hci_disable_intr(rtwdev); @@ -1224,14 +1247,14 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) rtw89_phy_init_rf_reg(rtwdev, true); - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_FW_RESTORE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); return ret; } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n"); return ret; @@ -1240,27 +1263,27 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) if (!is_conn) rtw89_cam_reset_keys(rtwdev); - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, !is_conn); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } if (is_conn) { - ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); + ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->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); + rtw89_phy_ra_assoc(rtwdev, rtwsta_link); + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); } if (chip_gen == RTW89_CHIP_BE) @@ -1363,21 +1386,20 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev) static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) { - struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *vif = rtw_wow->wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int ret; ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); if (ret) rtw89_err(rtwdev, "cfg ppdu status\n"); - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); return ret; } static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct list_head *pkt_list = &rtw_wow->pno_pkt_list; @@ -1391,7 +1413,7 @@ static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, } static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -1401,7 +1423,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, int ret; for (i = 0; i < num; i++) { - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, nd_config->match_sets[i].ssid.ssid, nd_config->match_sets[i].ssid.ssid_len, nd_config->ie_len); @@ -1413,7 +1435,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { kfree_skb(skb); - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); return -ENOMEM; } @@ -1421,7 +1443,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, if (ret) { kfree_skb(skb); kfree(info); - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); return ret; } @@ -1436,20 +1458,19 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int interval = rtw_wow->nd_config->scan_plans[0].interval; struct rtw89_scan_option opt = {}; int ret; if (enable) { - ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif); + ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update probe request failed\n"); return ret; } - ret = mac->add_chan_list_pno(rtwdev, rtwvif); + ret = mac->add_chan_list_pno(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update channel list failed\n"); return ret; @@ -1471,7 +1492,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) opt.opch_end = RTW89_CHAN_INVALID; } - mac->scan_offload(rtwdev, &opt, rtwvif, true); + mac->scan_offload(rtwdev, &opt, rtwvif_link, true); return 0; } @@ -1479,8 +1500,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; int ret; if (rtw89_wow_no_link(rtwdev)) { @@ -1499,25 +1519,25 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) rtw89_wow_pattern_write(rtwdev); rtw89_wow_construct_key_info(rtwdev); - ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable keep alive\n"); return ret; } - ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n"); return ret; } - ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable GTK offload\n"); return ret; } - ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, true); if (ret) rtw89_warn(rtwdev, "wow: failed to enable arp offload\n"); } @@ -1548,8 +1568,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; int ret; if (rtw89_wow_no_link(rtwdev)) { @@ -1559,35 +1578,35 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) return ret; } - ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable pno\n"); return ret; } - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); } else { rtw89_wow_pattern_clear(rtwdev); - ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable keep alive\n"); return ret; } - ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n"); return ret; } - ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable GTK offload\n"); return ret; } - ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, false); if (ret) rtw89_warn(rtwdev, "wow: failed to disable arp offload\n"); diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h index 3fbc2b87c058..f91991e8f2e3 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.h +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -97,18 +97,16 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) #ifdef CONFIG_PM static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - return rtwvif->net_type == RTW89_NET_TYPE_INFRA; + return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA; } static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - return rtwvif->net_type == RTW89_NET_TYPE_NO_LINK; + return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK; } static inline bool rtw_wow_has_mgd_features(struct rtw89_dev *rtwdev) |