diff options
72 files changed, 2413 insertions, 625 deletions
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c index 8857bb542c7f..0c5c66401daa 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c @@ -1041,10 +1041,11 @@ static void rtl8187_stop(struct ieee80211_hw *dev, bool suspend) rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + usb_kill_anchored_urbs(&priv->anchored); + while ((skb = skb_dequeue(&priv->b_tx_status.queue))) dev_kfree_skb_any(skb); - usb_kill_anchored_urbs(&priv->anchored); mutex_unlock(&priv->conf_mutex); if (!priv->is_rtl8187b) diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 898f597f70a9..d080469264cf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -572,8 +572,11 @@ remap: dma_map_single(&rtlpci->pdev->dev, skb_tail_pointer(skb), rtlpci->rxbuffersize, DMA_FROM_DEVICE); bufferaddress = *((dma_addr_t *)skb->cb); - if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) + if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) { + if (!new_skb) + kfree_skb(skb); return 0; + } rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; if (rtlpriv->use_new_trx_flow) { /* skb->cb may be 64 bit address */ @@ -802,13 +805,19 @@ new_trx_end: skb = new_skb; no_new: if (rtlpriv->use_new_trx_flow) { - _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, - rxring_idx, - rtlpci->rx_ring[rxring_idx].idx); + if (!_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, + rxring_idx, + rtlpci->rx_ring[rxring_idx].idx)) { + if (new_skb) + dev_kfree_skb_any(skb); + } } else { - _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, - rxring_idx, - rtlpci->rx_ring[rxring_idx].idx); + if (!_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, + rxring_idx, + rtlpci->rx_ring[rxring_idx].idx)) { + if (new_skb) + dev_kfree_skb_any(skb); + } if (rtlpci->rx_ring[rxring_idx].idx == rtlpci->rxringcount - 1) rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index d122f1eb345e..53c32e1de7e4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -1738,9 +1738,9 @@ static void read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 2ad4523d1bef..79c6e0901e57 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -190,7 +190,7 @@ static bool rtl88e_get_btc_status(void) return false; } -static struct rtl_hal_ops rtl8188ee_hal_ops = { +static const struct rtl_hal_ops rtl8188ee_hal_ops = { .init_sw_vars = rtl88e_init_sw_vars, .deinit_sw_vars = rtl88e_deinit_sw_vars, .read_eeprom_info = rtl88ee_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 0bc915723b93..5ca6b49e73c7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -1412,9 +1412,9 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, rtl92ce_enable_interrupt(hw); } -static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index ce7c28d9c874..f06b159f975d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -167,7 +167,7 @@ static void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) } } -static struct rtl_hal_ops rtl8192ce_hal_ops = { +static const struct rtl_hal_ops rtl8192ce_hal_ops = { .init_sw_vars = rtl92c_init_sw_vars, .deinit_sw_vars = rtl92c_deinit_sw_vars, .read_eeprom_info = rtl92ce_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 0195c9a3e9e8..ec5d558609fe 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -95,9 +95,9 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) } } -static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index c9b9e2bc90cc..00a6778df704 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -81,7 +81,7 @@ static bool rtl92cu_get_btc_status(void) return false; } -static struct rtl_hal_ops rtl8192cu_hal_ops = { +static const struct rtl_hal_ops rtl8192cu_hal_ops = { .init_sw_vars = rtl92cu_init_sw_vars, .deinit_sw_vars = rtl92cu_deinit_sw_vars, .read_chip_version = rtl92c_read_chip_version, @@ -156,7 +156,7 @@ static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = { .usb_mq_to_hwq = rtl8192cu_mq_to_hwq, }; -static struct rtl_hal_cfg rtl92cu_hal_cfg = { +static const struct rtl_hal_cfg rtl92cu_hal_cfg = { .name = "rtl92c_usb", .alt_fw_name = "rtlwifi/rtl8192cufw.bin", .ops = &rtl8192cu_hal_ops, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index e36e4aeb9a95..7612c22a9842 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -184,7 +184,7 @@ static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw) skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]); } -static struct rtl_hal_ops rtl8192de_hal_ops = { +static const struct rtl_hal_ops rtl8192de_hal_ops = { .init_sw_vars = rtl92d_init_sw_vars, .deinit_sw_vars = rtl92d_deinit_sw_vars, .read_eeprom_info = rtl92d_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index d4da5cdc8414..48a3c94606be 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -1731,7 +1731,7 @@ void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, rtl92ee_enable_interrupt(hw); } -static u8 _rtl92ee_get_chnl_group(u8 chnl) +static __always_inline u8 _rtl92ee_get_chnl_group(u8 chnl) { u8 group = 0; @@ -2009,8 +2009,9 @@ static void _rtl8192ee_read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo) +static noinline_for_stack void +_rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index 162e734d5b08..181dd7823b26 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -176,7 +176,7 @@ static bool rtl92ee_get_btc_status(void) return true; } -static struct rtl_hal_ops rtl8192ee_hal_ops = { +static const struct rtl_hal_ops rtl8192ee_hal_ops = { .init_sw_vars = rtl92ee_init_sw_vars, .deinit_sw_vars = rtl92ee_deinit_sw_vars, .read_eeprom_info = rtl92ee_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index e63c67b1861b..1cf801feb45e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -221,7 +221,7 @@ static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, return true; } -static struct rtl_hal_ops rtl8192se_hal_ops = { +static const struct rtl_hal_ops rtl8192se_hal_ops = { .init_sw_vars = rtl92s_init_sw_vars, .deinit_sw_vars = rtl92s_deinit_sw_vars, .read_eeprom_info = rtl92se_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index 6991713a66d0..21b827f519b6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -1381,9 +1381,9 @@ static u8 _rtl8723e_get_chnl_group(u8 chnl) return group; } -static void _rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 048744166a92..dcd7cdb96aa4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -183,7 +183,7 @@ static bool is_fw_header(struct rtlwifi_firmware_header *hdr) return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x2300; } -static struct rtl_hal_ops rtl8723e_hal_ops = { +static const struct rtl_hal_ops rtl8723e_hal_ops = { .init_sw_vars = rtl8723e_init_sw_vars, .deinit_sw_vars = rtl8723e_deinit_sw_vars, .read_eeprom_info = rtl8723e_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index bcfc53af4c1a..e1f811218894 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -1935,9 +1935,9 @@ static void _rtl8723be_read_power_value_fromprom(struct ieee80211_hw *hw, } } -static void _rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index 0a92d0325098..5967df08e34e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -187,7 +187,7 @@ static bool is_fw_header(struct rtlwifi_firmware_header *hdr) return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x5300; } -static struct rtl_hal_ops rtl8723be_hal_ops = { +static const struct rtl_hal_ops rtl8723be_hal_ops = { .init_sw_vars = rtl8723be_init_sw_vars, .deinit_sw_vars = rtl8723be_deinit_sw_vars, .read_eeprom_info = rtl8723be_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index f4b232f038a9..a5a34b5edcfd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -2782,9 +2782,9 @@ static void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); } #endif -static void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) +static noinline_for_stack void +_rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); @@ -3064,10 +3064,12 @@ static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_ 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[] = {RTL_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[] = { + RTL_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; if (b_pseudo_test) { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index b5266e560416..1557d32efdd2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -229,7 +229,7 @@ static bool rtl8821ae_get_btc_status(void) return true; } -static struct rtl_hal_ops rtl8821ae_hal_ops = { +static const struct rtl_hal_ops rtl8821ae_hal_ops = { .init_sw_vars = rtl8821ae_init_sw_vars, .deinit_sw_vars = rtl8821ae_deinit_sw_vars, .read_eeprom_info = rtl8821ae_read_eeprom_info, diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 4fc78b882080..c68a9fff6808 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -521,7 +521,7 @@ rtw_fw_send_general_info(struct rtw_dev *rtwdev) u8 h2c_pkt[H2C_PKT_SIZE] = {0}; u16 total_size = H2C_PKT_HDR_SIZE + 4; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO); @@ -544,7 +544,7 @@ rtw_fw_send_phydm_info(struct rtw_dev *rtwdev) u16 total_size = H2C_PKT_HDR_SIZE + 8; u8 fw_rf_type = 0; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; if (hal->rf_type == RF_1T1R) @@ -1480,7 +1480,7 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, bckp[2] = rtw_read8(rtwdev, REG_BCN_CTRL); - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { rtw_write32_set(rtwdev, REG_DWBCN0_CTRL, BIT_BCN_VALID); } else { pg_addr &= BIT_MASK_BCN_HEAD_1_V1; @@ -1509,7 +1509,7 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, goto restore; } - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { bcn_valid_addr = REG_DWBCN0_CTRL; bcn_valid_mask = BIT_BCN_VALID; } else { diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index f66d1b302dc5..011b81c82f3b 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -41,7 +41,7 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, } rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32); - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL); @@ -67,7 +67,7 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_RSV_CTRL, 0); - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { if (rtw_read32(rtwdev, REG_SYS_CFG1) & BIT_LDO) rtw_write8(rtwdev, REG_LDO_SWR_CTRL, LDO_SEL); else @@ -278,7 +278,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) bool cur_pwr; int ret; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); /* Check FW still exist or not */ @@ -369,7 +369,7 @@ static int __rtw_mac_init_system_cfg_legacy(struct rtw_dev *rtwdev) static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_mac_init_system_cfg_legacy(rtwdev); return __rtw_mac_init_system_cfg(rtwdev); @@ -981,7 +981,7 @@ out: static int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_download_firmware_legacy(rtwdev, fw); return __rtw_download_firmware(rtwdev, fw); @@ -1122,7 +1122,7 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_CR, 0); rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { @@ -1145,7 +1145,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) /* config rsvd page num */ fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num; fifo->txff_pg_num = chip->txff_size / chip->page_size; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num; else fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num + @@ -1163,7 +1163,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num; cur_pg_addr = fifo->txff_pg_num; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { cur_pg_addr -= csi_buf_pg_num; fifo->rsvd_csibuf_addr = cur_pg_addr; cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM; @@ -1292,7 +1292,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num - pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __priority_queue_cfg_legacy(rtwdev, pg_tbl, pubq_num); else return __priority_queue_cfg(rtwdev, pg_tbl, pubq_num); @@ -1308,7 +1308,7 @@ static int init_h2c(struct rtw_dev *rtwdev) u32 h2cq_free; u32 wp, rp; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return 0; h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT; @@ -1375,7 +1375,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) u8 value8; rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE); - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1); value8 &= 0xF0; /* For rxdesc len = 0 issue */ diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index c4de5d114eda..97756bdf57b2 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -636,6 +636,7 @@ void rtw_fw_recovery(struct rtw_dev *rtwdev) if (!test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)) ieee80211_queue_work(rtwdev->hw, &rtwdev->fw_recovery_work); } +EXPORT_SYMBOL(rtw_fw_recovery); static void __fw_recovery_work(struct rtw_dev *rtwdev) { @@ -1765,7 +1766,7 @@ static void __update_firmware_info_legacy(struct rtw_dev *rtwdev, static void update_firmware_info(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) __update_firmware_info_legacy(rtwdev, fw); else __update_firmware_info(rtwdev, fw); @@ -2218,7 +2219,6 @@ EXPORT_SYMBOL(rtw_core_deinit); int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) { - bool sta_mode_only = rtwdev->hci.type == RTW_HCI_TYPE_SDIO; struct rtw_hal *hal = &rtwdev->hal; int max_tx_headroom = 0; int ret; @@ -2248,12 +2248,9 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); - if (sta_mode_only) - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - else - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_ADHOC); + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->available_antennas_tx = hal->antenna_tx; hw->wiphy->available_antennas_rx = hal->antenna_rx; @@ -2264,7 +2261,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS; hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev); - if (!sta_mode_only && rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { hw->wiphy->iface_combinations = rtw_iface_combs; hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs); } diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 7ae67143e909..b42538cce359 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1173,8 +1173,8 @@ struct rtw_pwr_track_tbl { }; enum rtw_wlan_cpu { - RTW_WCPU_11AC, - RTW_WCPU_11N, + RTW_WCPU_3081, + RTW_WCPU_8051, }; enum rtw_fw_fifo_sel { @@ -2166,14 +2166,14 @@ static inline void rtw_chip_efuse_grant_off(struct rtw_dev *rtwdev) rtwdev->chip->ops->efuse_grant(rtwdev, false); } -static inline bool rtw_chip_wcpu_11n(struct rtw_dev *rtwdev) +static inline bool rtw_chip_wcpu_8051(struct rtw_dev *rtwdev) { - return rtwdev->chip->wlan_cpu == RTW_WCPU_11N; + return rtwdev->chip->wlan_cpu == RTW_WCPU_8051; } -static inline bool rtw_chip_wcpu_11ac(struct rtw_dev *rtwdev) +static inline bool rtw_chip_wcpu_3081(struct rtw_dev *rtwdev) { - return rtwdev->chip->wlan_cpu == RTW_WCPU_11AC; + return rtwdev->chip->wlan_cpu == RTW_WCPU_3081; } static inline bool rtw_chip_has_rx_ldpc(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 7f2b6dc21f56..56b16186d3aa 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -405,7 +405,7 @@ static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma; rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma); - if (!rtw_chip_wcpu_11n(rtwdev)) { + if (!rtw_chip_wcpu_8051(rtwdev)) { len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0; @@ -467,7 +467,7 @@ static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff); /* reset H2C Queue index in a single write */ - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HOST_IDX | BIT_CLR_H2CQ_HW_IDX); } @@ -487,7 +487,7 @@ static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0] & ~imr0_unmask); rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); rtwpci->irq_enabled = true; @@ -507,7 +507,7 @@ static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, rtw_write32(rtwdev, RTK_PCI_HIMR0, 0); rtw_write32(rtwdev, RTK_PCI_HIMR1, 0); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HIMR3, 0); rtwpci->irq_enabled = false; @@ -1125,7 +1125,7 @@ static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0); irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3); else irq_status[3] = 0; @@ -1134,7 +1134,7 @@ static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, irq_status[3] &= rtwpci->irq_mask[3]; rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]); rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]); spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); @@ -1707,6 +1707,43 @@ static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev) free_netdev(rtwpci->netdev); } +static pci_ers_result_t rtw_pci_io_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + netif_device_detach(netdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t rtw_pci_io_slot_reset(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw_dev *rtwdev = hw->priv; + + rtw_fw_recovery(rtwdev); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void rtw_pci_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + /* ack any pending wake events, disable PME */ + pci_enable_wake(pdev, PCI_D0, 0); + + netif_device_attach(netdev); +} + +const struct pci_error_handlers rtw_pci_err_handler = { + .error_detected = rtw_pci_io_err_detected, + .slot_reset = rtw_pci_io_slot_reset, + .resume = rtw_pci_io_resume, +}; +EXPORT_SYMBOL(rtw_pci_err_handler); + int rtw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index 13988db1cb4c..8ffdea11378f 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -231,6 +231,7 @@ struct rtw_pci { }; extern const struct dev_pm_ops rtw_pm_ops; +extern const struct pci_error_handlers rtw_pci_err_handler; int rtw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); void rtw_pci_remove(struct pci_dev *pdev); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c index 9e6700c43a63..03475af973b5 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c @@ -1882,7 +1882,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = { .id = RTW_CHIP_TYPE_8703B, .fw_name = "rtw88/rtw8703b_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 31876e708f9e..bf69f5b06ce2 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2116,7 +2116,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = { .ops = &rtw8723d_ops, .id = RTW_CHIP_TYPE_8723D, .fw_name = "rtw88/rtw8723d_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c index 87c8bc9d18a9..c6d0c88e5d81 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723de.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c @@ -23,6 +23,7 @@ static struct pci_driver rtw_8723de_driver = { .remove = rtw_pci_remove, .driver.pm = &rtw_pm_ops, .shutdown = rtw_pci_shutdown, + .err_handler = &rtw_pci_err_handler, }; module_pci_driver(rtw_8723de_driver); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c index c2ef41767ff9..03b441639611 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c @@ -1038,7 +1038,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = { .ops = &rtw8812a_ops, .id = RTW_CHIP_TYPE_8812A, .fw_name = "rtw88/rtw8812a_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814a.c b/drivers/net/wireless/realtek/rtw88/rtw8814a.c index 44dd3090484b..4a1f850d05c8 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8814a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8814a.c @@ -2180,7 +2180,7 @@ const struct rtw_chip_info rtw8814a_hw_spec = { .ops = &rtw8814a_ops, .id = RTW_CHIP_TYPE_8814A, .fw_name = "rtw88/rtw8814a_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c index 413aec694c33..1d02ea400b2e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c @@ -1138,7 +1138,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = { .ops = &rtw8821a_ops, .id = RTW_CHIP_TYPE_8821A, .fw_name = "rtw88/rtw8821a_fw.bin", - .wlan_cpu = RTW_WCPU_11N, + .wlan_cpu = RTW_WCPU_8051, .tx_pkt_desc_sz = 40, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index 413130a30ca9..a2a358d6033f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -1973,7 +1973,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { .ops = &rtw8821c_ops, .id = RTW_CHIP_TYPE_8821C, .fw_name = "rtw88/rtw8821c_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c index 40637c079d99..52a19cb17daa 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c @@ -27,6 +27,7 @@ static struct pci_driver rtw_8821ce_driver = { .remove = rtw_pci_remove, .driver.pm = &rtw_pm_ops, .shutdown = rtw_pci_shutdown, + .err_handler = &rtw_pci_err_handler, }; module_pci_driver(rtw_8821ce_driver); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 710126379e77..bb5c41905afe 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2514,7 +2514,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { .ops = &rtw8822b_ops, .id = RTW_CHIP_TYPE_8822B, .fw_name = "rtw88/rtw8822b_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.c b/drivers/net/wireless/realtek/rtw88/rtw8822be.c index 0bb9f70e7920..dda597d73219 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822be.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822be.c @@ -23,6 +23,7 @@ static struct pci_driver rtw_8822be_driver = { .remove = rtw_pci_remove, .driver.pm = &rtw_pm_ops, .shutdown = rtw_pci_shutdown, + .err_handler = &rtw_pci_err_handler, }; module_pci_driver(rtw_8822be_driver); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 0ce6aa10493e..58c1958e6170 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -5333,7 +5333,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, .fw_name = "rtw88/rtw8822c_fw.bin", - .wlan_cpu = RTW_WCPU_11AC, + .wlan_cpu = RTW_WCPU_3081, .tx_pkt_desc_sz = 48, .tx_buf_desc_sz = 16, .rx_pkt_desc_sz = 24, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c index 9def732480af..7ae95415c224 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c @@ -27,6 +27,7 @@ static struct pci_driver rtw_8822ce_driver = { .remove = rtw_pci_remove, .driver.pm = &rtw_pm_ops, .shutdown = rtw_pci_shutdown, + .err_handler = &rtw_pci_err_handler, }; module_pci_driver(rtw_8822ce_driver); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index e733ed846123..cc2d4fef3587 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -547,7 +547,7 @@ static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue, { unsigned int pages_free, pages_needed; - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { u32 free_txpg; free_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG); @@ -1030,7 +1030,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) u32 rx_len, hisr, total_rx_bytes = 0; do { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN); else rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN); @@ -1042,7 +1042,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) total_rx_bytes += rx_len; - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { /* Stop if no more RX requests are pending, even if * rx_len could be greater than zero in the next * iteration. This is needed because the RX buffer may @@ -1054,7 +1054,7 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) */ hisr = rtw_read32(rtwdev, REG_SDIO_HISR); } else { - /* RTW_WCPU_11AC chips have improved hardware or + /* RTW_WCPU_3081 chips have improved hardware or * firmware and can use rx_len unconditionally. */ hisr = REG_SDIO_HISR_RX_REQUEST; diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 806f42429a29..6f10235647a1 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -170,22 +170,26 @@ int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev, static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx idx, - const struct cfg80211_chan_def *chandef, - bool from_stack) + const struct cfg80211_chan_def *chandef) { struct rtw89_hal *hal = &rtwdev->hal; hal->chanctx[idx].chandef = *chandef; - - if (from_stack) - set_bit(idx, hal->entity_map); } void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx idx, const struct cfg80211_chan_def *chandef) { - __rtw89_config_entity_chandef(rtwdev, idx, chandef, true); + struct rtw89_hal *hal = &rtwdev->hal; + + if (!chandef) { + clear_bit(idx, hal->entity_map); + return; + } + + __rtw89_config_entity_chandef(rtwdev, idx, chandef); + set_bit(idx, hal->entity_map); } void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev, @@ -227,7 +231,7 @@ static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev) struct cfg80211_chan_def chandef = {0}; rtw89_get_default_chandef(&chandef); - __rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef, false); + __rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef); } void rtw89_entity_init(struct rtw89_dev *rtwdev) @@ -265,6 +269,8 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif; int idx; + w->registered_chanctxs = bitmap_weight(hal->entity_map, NUM_OF_RTW89_CHANCTX); + for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) { cfg = hal->chanctx[idx].cfg; if (!cfg) { @@ -473,7 +479,8 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev) bitmap_zero(recalc_map, NUM_OF_RTW89_CHANCTX); fallthrough; case 0: - rtw89_config_default_chandef(rtwdev); + if (!w.registered_chanctxs) + rtw89_config_default_chandef(rtwdev); set_bit(RTW89_CHANCTX_0, recalc_map); fallthrough; case 1: @@ -953,6 +960,7 @@ static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) } sel.bind_vif[i] = rtwvif_link; + rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, NULL); } ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel); @@ -1265,6 +1273,8 @@ static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev, if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME) small_bcn_ofst = true; + else if (bcn_ofst < aux->duration - aux->limit.max_toa) + small_bcn_ofst = true; else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME) small_bcn_ofst = false; else @@ -1595,6 +1605,35 @@ static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev) return false; } +void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + mcc_prepare_done_work.work); + + lockdep_assert_wiphy(wiphy); + + ieee80211_wake_queues(rtwdev->hw); +} + +static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start) +{ + struct rtw89_mcc_info *mcc = &rtwdev->mcc; + struct rtw89_mcc_config *config = &mcc->config; + + if (start) { + ieee80211_stop_queues(rtwdev->hw); + + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work, + usecs_to_jiffies(config->prepare_delay)); + } else { + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work, 0); + wiphy_delayed_work_flush(rtwdev->hw->wiphy, + &rtwdev->mcc_prepare_done_work); + } +} + static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; @@ -1630,6 +1669,8 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) config->start_tsf = start_tsf; config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf; + config->prepare_delay = start_tsf - tsf; + return 0; } @@ -2177,6 +2218,18 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) rtw89_mcc_handle_beacon_noa(rtwdev, false); } +static bool rtw89_mcc_ignore_bcn(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role) +{ + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + + if (role->is_go) + return true; + else if (chip_gen == RTW89_CHIP_BE && role->is_gc) + return true; + else + return false; +} + static int rtw89_mcc_start(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; @@ -2200,6 +2253,15 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) else mcc->mode = RTW89_MCC_MODE_GC_STA; + if (rtw89_mcc_ignore_bcn(rtwdev, ref)) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false); + } else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false); + } else { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true); + } + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode); mcc->group = RTW89_MCC_DFLT_GROUP; @@ -2219,6 +2281,8 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); rtw89_mcc_start_beacon_noa(rtwdev); + + rtw89_mcc_prepare(rtwdev, true); return 0; } @@ -2307,6 +2371,8 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); rtw89_mcc_stop_beacon_noa(rtwdev); + + rtw89_mcc_prepare(rtwdev, false); } static int rtw89_mcc_update(struct rtw89_dev *rtwdev) @@ -2362,15 +2428,44 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev) return 0; } +static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *role) +{ + struct ieee80211_vif *vif; + int ret; + + ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false, + RTW89_MCC_PROBE_TIMEOUT); + if (ret) + role->probe_count++; + else + role->probe_count = 0; + + if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES) + return; + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "MCC <macid %d> can not detect AP\n", role->rtwvif_link->mac_id); + vif = rtwvif_link_to_vif(role->rtwvif_link); + ieee80211_connection_loss(vif); +} + static void rtw89_mcc_track(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; struct rtw89_mcc_config *config = &mcc->config; struct rtw89_mcc_pattern *pattern = &config->pattern; + struct rtw89_mcc_role *ref = &mcc->role_ref; + struct rtw89_mcc_role *aux = &mcc->role_aux; u16 tolerance; u16 bcn_ofst; u16 diff; + if (rtw89_mcc_ignore_bcn(rtwdev, ref)) + rtw89_mcc_detect_connection(rtwdev, aux); + else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) + rtw89_mcc_detect_connection(rtwdev, ref); + if (mcc->mode != RTW89_MCC_MODE_GC_STA) return; @@ -2619,6 +2714,201 @@ void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT); } +static enum rtw89_mr_wtype __rtw89_query_mr_wtype(struct rtw89_dev *rtwdev) +{ + struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + enum rtw89_chanctx_idx chanctx_idx; + struct ieee80211_vif *vif; + struct rtw89_vif *rtwvif; + unsigned int num_mld = 0; + unsigned int num_ml = 0; + unsigned int cnt = 0; + u8 role_idx; + u8 idx; + + for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { + rtwvif = mgnt->active_roles[role_idx]; + if (!rtwvif) + continue; + + cnt++; + + vif = rtwvif_to_vif(rtwvif); + if (!ieee80211_vif_is_mld(vif)) + continue; + + num_mld++; + + for (idx = 0; idx < __RTW89_MLD_MAX_LINK_NUM; idx++) { + chanctx_idx = mgnt->chanctx_tbl[role_idx][idx]; + if (chanctx_idx != RTW89_CHANCTX_IDLE) + num_ml++; + } + } + + if (num_mld > 1) + goto err; + + switch (cnt) { + case 0: + return RTW89_MR_WTYPE_NONE; + case 1: + if (!num_mld) + return RTW89_MR_WTYPE_NONMLD; + switch (num_ml) { + case 1: + return RTW89_MR_WTYPE_MLD1L1R; + case 2: + return RTW89_MR_WTYPE_MLD2L1R; + default: + break; + } + break; + case 2: + if (!num_mld) + return RTW89_MR_WTYPE_NONMLD_NONMLD; + switch (num_ml) { + case 1: + return RTW89_MR_WTYPE_MLD1L1R_NONMLD; + case 2: + return RTW89_MR_WTYPE_MLD2L1R_NONMLD; + default: + break; + } + break; + default: + break; + } + +err: + rtw89_warn(rtwdev, "%s: unhandled cnt %u mld %u ml %u\n", __func__, + cnt, num_mld, num_ml); + return RTW89_MR_WTYPE_UNKNOWN; +} + +static enum rtw89_mr_wmode __rtw89_query_mr_wmode(struct rtw89_dev *rtwdev, + u8 inst_idx) +{ + struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + unsigned int num[NUM_NL80211_IFTYPES] = {}; + enum rtw89_chanctx_idx chanctx_idx; + struct ieee80211_vif *vif; + struct rtw89_vif *rtwvif; + unsigned int cnt = 0; + u8 role_idx; + + if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM)) + return RTW89_MR_WMODE_UNKNOWN; + + for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { + chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx]; + if (chanctx_idx == RTW89_CHANCTX_IDLE) + continue; + + rtwvif = mgnt->active_roles[role_idx]; + if (unlikely(!rtwvif)) + continue; + + vif = rtwvif_to_vif(rtwvif); + num[vif->type]++; + cnt++; + } + + switch (cnt) { + case 0: + return RTW89_MR_WMODE_NONE; + case 1: + if (num[NL80211_IFTYPE_STATION]) + return RTW89_MR_WMODE_1CLIENT; + if (num[NL80211_IFTYPE_AP]) + return RTW89_MR_WMODE_1AP; + break; + case 2: + if (num[NL80211_IFTYPE_STATION] == 2) + return RTW89_MR_WMODE_2CLIENTS; + if (num[NL80211_IFTYPE_AP] == 2) + return RTW89_MR_WMODE_2APS; + if (num[NL80211_IFTYPE_STATION] && num[NL80211_IFTYPE_AP]) + return RTW89_MR_WMODE_1AP_1CLIENT; + break; + default: + break; + } + + rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt); + return RTW89_MR_WMODE_UNKNOWN; +} + +static enum rtw89_mr_ctxtype __rtw89_query_mr_ctxtype(struct rtw89_dev *rtwdev, + u8 inst_idx) +{ + struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + DECLARE_BITMAP(map, NUM_OF_RTW89_CHANCTX) = {}; + unsigned int num[RTW89_BAND_NUM] = {}; + enum rtw89_chanctx_idx chanctx_idx; + const struct rtw89_chan *chan; + unsigned int cnt = 0; + u8 role_idx; + + if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM)) + return RTW89_MR_CTX_UNKNOWN; + + for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { + chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx]; + if (chanctx_idx == RTW89_CHANCTX_IDLE) + continue; + + if (__test_and_set_bit(chanctx_idx, map)) + continue; + + chan = rtw89_chan_get(rtwdev, chanctx_idx); + num[chan->band_type]++; + cnt++; + } + + switch (cnt) { + case 0: + return RTW89_MR_CTX_NONE; + case 1: + if (num[RTW89_BAND_2G]) + return RTW89_MR_CTX1_2GHZ; + if (num[RTW89_BAND_5G]) + return RTW89_MR_CTX1_5GHZ; + if (num[RTW89_BAND_6G]) + return RTW89_MR_CTX1_6GHZ; + break; + case 2: + if (num[RTW89_BAND_2G] == 2) + return RTW89_MR_CTX2_2GHZ; + if (num[RTW89_BAND_5G] == 2) + return RTW89_MR_CTX2_5GHZ; + if (num[RTW89_BAND_6G] == 2) + return RTW89_MR_CTX2_6GHZ; + if (num[RTW89_BAND_2G] && num[RTW89_BAND_5G]) + return RTW89_MR_CTX2_2GHZ_5GHZ; + if (num[RTW89_BAND_2G] && num[RTW89_BAND_6G]) + return RTW89_MR_CTX2_2GHZ_6GHZ; + if (num[RTW89_BAND_5G] && num[RTW89_BAND_6G]) + return RTW89_MR_CTX2_5GHZ_6GHZ; + break; + default: + break; + } + + rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt); + return RTW89_MR_CTX_UNKNOWN; +} + +void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx, + struct rtw89_mr_chanctx_info *info) +{ + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + info->wtype = __rtw89_query_mr_wtype(rtwdev); + info->wmode = __rtw89_query_mr_wmode(rtwdev, inst_idx); + info->ctxtype = __rtw89_query_mr_ctxtype(rtwdev, inst_idx); +} + void rtw89_chanctx_track(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; @@ -2782,10 +3072,9 @@ int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx) { - struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; - clear_bit(cfg->idx, hal->entity_map); + rtw89_config_entity_chandef(rtwdev, cfg->idx, NULL); } void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, @@ -2816,6 +3105,9 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, rtwvif_link->chanctx_assigned = true; cfg->ref_count++; + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + if (list_empty(&rtwvif->mgnt_entry)) list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list); @@ -2855,6 +3147,9 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, rtwvif_link->chanctx_assigned = false; cfg->ref_count--; + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + if (!rtw89_vif_is_active_role(rtwvif)) list_del_init(&rtwvif->mgnt_entry); @@ -2906,3 +3201,35 @@ out: break; } } + +int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *old_ctx, + struct ieee80211_chanctx_conf *new_ctx, + bool replace) +{ + int ret; + + rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, old_ctx); + + if (!replace) + goto assign; + + rtw89_chanctx_ops_remove(rtwdev, old_ctx); + ret = rtw89_chanctx_ops_add(rtwdev, new_ctx); + if (ret) { + rtw89_err(rtwdev, "%s: failed to add chanctx: %d\n", + __func__, ret); + return ret; + } + +assign: + ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, new_ctx); + if (ret) { + rtw89_err(rtwdev, "%s: failed to assign chanctx: %d\n", + __func__, ret); + return ret; + } + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 2a25563593af..57355cb3d765 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -19,6 +19,9 @@ #define RTW89_MCC_MIN_RX_BCN_TIME 10 #define RTW89_MCC_DFLT_BCN_OFST_TIME 40 +#define RTW89_MCC_PROBE_TIMEOUT 100 +#define RTW89_MCC_PROBE_MAX_TRIES 3 + #define RTW89_MCC_MIN_GO_DURATION \ (RTW89_MCC_EARLY_TX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME) @@ -28,7 +31,7 @@ #define RTW89_MCC_DFLT_GROUP 0 #define RTW89_MCC_NEXT_GROUP(cur) (((cur) + 1) % 4) -#define RTW89_MCC_DFLT_TX_NULL_EARLY 3 +#define RTW89_MCC_DFLT_TX_NULL_EARLY 7 #define RTW89_MCC_DFLT_COURTESY_SLOT 3 #define RTW89_MCC_REQ_COURTESY_TIME 5 @@ -41,6 +44,49 @@ #define NUM_OF_RTW89_MCC_ROLES 2 +enum rtw89_mr_wtype { + RTW89_MR_WTYPE_NONE, + RTW89_MR_WTYPE_NONMLD, + RTW89_MR_WTYPE_MLD1L1R, + RTW89_MR_WTYPE_MLD2L1R, + RTW89_MR_WTYPE_MLD2L2R, + RTW89_MR_WTYPE_NONMLD_NONMLD, + RTW89_MR_WTYPE_MLD1L1R_NONMLD, + RTW89_MR_WTYPE_MLD2L1R_NONMLD, + RTW89_MR_WTYPE_MLD2L2R_NONMLD, + RTW89_MR_WTYPE_UNKNOWN, +}; + +enum rtw89_mr_wmode { + RTW89_MR_WMODE_NONE, + RTW89_MR_WMODE_1CLIENT, + RTW89_MR_WMODE_1AP, + RTW89_MR_WMODE_1AP_1CLIENT, + RTW89_MR_WMODE_2CLIENTS, + RTW89_MR_WMODE_2APS, + RTW89_MR_WMODE_UNKNOWN, +}; + +enum rtw89_mr_ctxtype { + RTW89_MR_CTX_NONE, + RTW89_MR_CTX1_2GHZ, + RTW89_MR_CTX1_5GHZ, + RTW89_MR_CTX1_6GHZ, + RTW89_MR_CTX2_2GHZ, + RTW89_MR_CTX2_5GHZ, + RTW89_MR_CTX2_6GHZ, + RTW89_MR_CTX2_2GHZ_5GHZ, + RTW89_MR_CTX2_2GHZ_6GHZ, + RTW89_MR_CTX2_5GHZ_6GHZ, + RTW89_MR_CTX_UNKNOWN, +}; + +struct rtw89_mr_chanctx_info { + enum rtw89_mr_wtype wtype; + enum rtw89_mr_wmode wmode; + enum rtw89_mr_ctxtype ctxtype; +}; + enum rtw89_chanctx_pause_reasons { RTW89_CHANCTX_PAUSE_REASON_HW_SCAN, RTW89_CHANCTX_PAUSE_REASON_ROC, @@ -58,6 +104,7 @@ struct rtw89_chanctx_cb_parm { }; struct rtw89_entity_weight { + unsigned int registered_chanctxs; unsigned int active_chanctxs; unsigned int active_roles; }; @@ -116,6 +163,8 @@ void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work); void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev); void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, enum rtw89_chanctx_changes change); +void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx, + struct rtw89_mr_chanctx_info *info); void rtw89_chanctx_track(struct rtw89_dev *rtwdev); void rtw89_chanctx_pause(struct rtw89_dev *rtwdev, const struct rtw89_chanctx_pause_parm *parm); @@ -129,6 +178,8 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, #define rtw89_mgnt_chan_get(rtwdev, link_index) \ __rtw89_mgnt_chan_get(rtwdev, __func__, link_index) +void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work); + int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, @@ -142,5 +193,10 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx); +int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *old_ctx, + struct ieee80211_chanctx_conf *new_ctx, + bool replace); #endif diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 5ccf0cbaed2f..e4e6daf51a1b 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include "chan.h" #include "coex.h" #include "debug.h" #include "fw.h" @@ -10,7 +11,7 @@ #include "ps.h" #include "reg.h" -#define RTW89_COEX_VERSION 0x07000413 +#define RTW89_COEX_VERSION 0x09000013 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/ #define BTC_E2G_LIMIT_DEF 80 @@ -138,7 +139,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, }, {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0), .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, @@ -146,7 +147,23 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, + }, + {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 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 = 4, .fcxctrl = 7, .fcxinit = 7, + .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800, + .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, + }, + {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 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 = 4, .fcxctrl = 7, .fcxinit = 7, + .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800, + .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, }, {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, @@ -154,7 +171,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, @@ -162,7 +179,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, @@ -170,7 +187,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, @@ -178,7 +195,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, @@ -186,7 +203,15 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, + }, + {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 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 = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, + .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, @@ -194,7 +219,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, @@ -202,7 +227,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, - .max_role_num = 6, + .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, @@ -210,7 +235,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, @@ -218,7 +243,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, @@ -226,7 +251,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, /* keep it to be the last as default entry */ @@ -236,7 +261,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024, - .max_role_num = 5, + .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, }, }; @@ -269,6 +294,39 @@ static u32 chip_id_to_bt_rom_code_id(u32 id) } } +#define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e + +static const char *id_to_mlme_state(u32 id) +{ + switch (id) { + CASE_BTC_MLME_STATE(NO_LINK); + CASE_BTC_MLME_STATE(LINKING); + CASE_BTC_MLME_STATE(LINKED); + default: + return "unknown"; + } +} + +static char *chip_id_str(u32 id) +{ + switch (id) { + case RTL8852A: + return "RTL8852A"; + case RTL8852B: + return "RTL8852B"; + case RTL8852C: + return "RTL8852C"; + case RTL8852BT: + return "RTL8852BT"; + case RTL8851B: + return "RTL8851B"; + case RTL8922A: + return "RTL8922A"; + default: + return "UNKNOWN"; + } +} + struct rtw89_btc_btf_tlv { u8 type; u8 len; @@ -291,6 +349,7 @@ enum btc_btf_set_report_en { RPT_EN_BT_DEVICE_INFO, RPT_EN_BT_AFH_MAP, RPT_EN_BT_AFH_MAP_LE, + RPT_EN_BT_TX_PWR_LVL, RPT_EN_FW_STEP_INFO, RPT_EN_TEST, RPT_EN_WL_ALL, @@ -668,6 +727,27 @@ enum btc_wl_link_mode { BTC_WLINK_MAX }; +#define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e + +static const char *id_to_linkmode(u8 id) +{ + switch (id) { + CASE_BTC_WL_LINK_MODE(NOLINK); + CASE_BTC_WL_LINK_MODE(2G_STA); + CASE_BTC_WL_LINK_MODE(2G_AP); + CASE_BTC_WL_LINK_MODE(2G_GO); + CASE_BTC_WL_LINK_MODE(2G_GC); + CASE_BTC_WL_LINK_MODE(2G_SCC); + CASE_BTC_WL_LINK_MODE(2G_MCC); + CASE_BTC_WL_LINK_MODE(25G_MCC); + CASE_BTC_WL_LINK_MODE(25G_DBCC); + CASE_BTC_WL_LINK_MODE(5G); + CASE_BTC_WL_LINK_MODE(OTHER); + default: + return "unknown"; + } +} + enum btc_wl_mrole_type { BTC_WLMROLE_NONE = 0x0, BTC_WLMROLE_STA_GC, @@ -833,6 +913,9 @@ static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, return ret; } +#define BTC_BT_DEF_BR_TX_PWR 4 +#define BTC_BT_DEF_LE_TX_PWR 4 + static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) { struct rtw89_btc *btc = &rtwdev->btc; @@ -901,6 +984,9 @@ static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) if (type & BTC_RESET_MDINFO) memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); + + bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR; + bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR; } static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target) @@ -1324,6 +1410,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, u8 *prptbuf, u32 index) { struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_dm *dm = &btc->dm; struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; @@ -1366,23 +1453,29 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxbtcrpt == 1) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver; } else if (ver->fcxbtcrpt == 4) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver; } else if (ver->fcxbtcrpt == 5) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver; } else if (ver->fcxbtcrpt == 105) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver; pcinfo->req_fver = 5; break; } else if (ver->fcxbtcrpt == 8) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v8; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver; } else if (ver->fcxbtcrpt == 7) { pfinfo = &pfwinfo->rpt_ctrl.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7); + fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver; } else { goto err; } @@ -1393,9 +1486,11 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxtdma == 1) { pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); + fwsubver->fcxtdma = 0; } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) { pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); + fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver; } else { goto err; } @@ -1406,9 +1501,11 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxslots == 1) { pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1); + fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver; } else if (ver->fcxslots == 7) { pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7); + fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver; } else { goto err; } @@ -1421,22 +1518,27 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); + fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver; } else if (ver->fcxcysta == 3) { pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); + fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver; } else if (ver->fcxcysta == 4) { pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); + fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver; } else if (ver->fcxcysta == 5) { pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); + fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver; } else if (ver->fcxcysta == 7) { pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7; pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7); + fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver; } else { goto err; } @@ -1452,11 +1554,13 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * trace_step + offsetof(struct rtw89_btc_fbtc_steps_v2, step); + fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver; } else if (ver->fcxstep == 3) { pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * trace_step + offsetof(struct rtw89_btc_fbtc_steps_v3, step); + fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver; } else { goto err; } @@ -1467,12 +1571,15 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxnullsta == 1) { pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); + fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver; } else if (ver->fcxnullsta == 2) { pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); + fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver; } else if (ver->fcxnullsta == 7) { pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7); + fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver; } else { goto err; } @@ -1483,12 +1590,15 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxmreg == 1) { pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); + fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver; } else if (ver->fcxmreg == 2) { pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); + fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver; } else if (ver->fcxmreg == 7) { pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7); + fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver; } else { goto err; } @@ -1499,9 +1609,11 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxgpiodbg == 7) { pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7); + fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver; } else { pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1); + fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver; } pcinfo->req_fver = ver->fcxgpiodbg; break; @@ -1510,9 +1622,11 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxbtver == 1) { pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1); + fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver; } else if (ver->fcxbtver == 7) { pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7); + fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver; } pcinfo->req_fver = ver->fcxbtver; break; @@ -1521,12 +1635,15 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxbtscan == 1) { pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); + fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver; } else if (ver->fcxbtscan == 2) { pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); + fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver; } else if (ver->fcxbtscan == 7) { pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7); + fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver; } else { goto err; } @@ -1537,12 +1654,15 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (ver->fcxbtafh == 1) { pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); + fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver; } else if (ver->fcxbtafh == 2) { pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); + fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver; } else if (ver->fcxbtafh == 7) { pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7); + fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver; } else { goto err; } @@ -1552,6 +1672,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); + fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver; pcinfo->req_fver = ver->fcxbtdevinfo; break; default: @@ -2283,6 +2404,7 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) bit_map = BIT(6); break; case 3: + case 4: bit_map = BIT(5); break; default: @@ -2297,6 +2419,7 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) bit_map = BIT(5); break; case 3: + case 4: bit_map = BIT(6); break; default: @@ -2309,12 +2432,27 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) bit_map = BIT(8); break; case 3: + case 4: bit_map = BIT(7); break; default: break; } break; + case RPT_EN_BT_TX_PWR_LVL: + switch (ver->frptmap) { + case 0: + case 1: + case 2: + case 3: + break; + case 4: + bit_map = BIT(8); + break; + default: + break; + } + break; case RPT_EN_FW_STEP_INFO: switch (ver->frptmap) { case 1: @@ -2324,6 +2462,9 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) case 3: bit_map = BIT(8); break; + case 4: + bit_map = BIT(9); + break; default: break; } @@ -2341,6 +2482,9 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) case 3: bit_map = GENMASK(2, 0) | BIT(8); break; + case 4: + bit_map = GENMASK(2, 0) | BIT(9); + break; default: break; } @@ -2357,6 +2501,9 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) case 3: bit_map = GENMASK(7, 3); break; + case 4: + bit_map = GENMASK(8, 3); + break; default: break; } @@ -2373,6 +2520,9 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) case 3: bit_map = GENMASK(8, 0); break; + case 4: + bit_map = GENMASK(9, 0); + break; default: break; } @@ -2389,6 +2539,9 @@ static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) case 3: bit_map = GENMASK(8, 2); break; + case 4: + bit_map = GENMASK(9, 2); + break; default: break; } @@ -2678,6 +2831,16 @@ static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type) case CXDRVINFO_FDDT: case CXDRVINFO_MLO: case CXDRVINFO_OSI: + if (!ver->fcxosi) + return; + + if (ver->drvinfo_type == 2) + type = 7; + else + return; + + rtw89_fw_h2c_cxdrv_osi_info(rtwdev, type); + break; default: break; } @@ -2758,6 +2921,8 @@ static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map, { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; + struct rtw89_btc_fbtc_outsrc_set_info *osi = &dm->ost_info; + struct rtw89_mac_ax_wl_act *b = dm->gnt.bt; struct rtw89_mac_ax_gnt *g = dm->gnt.band; u8 i, bt_idx = dm->bt_select + 1; @@ -2806,21 +2971,35 @@ static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map, switch (wlact_state) { case BTC_WLACT_HW: - dm->gnt.bt[i].wlan_act_en = 0; - dm->gnt.bt[i].wlan_act = 0; + b[i].wlan_act_en = 0; + b[i].wlan_act = 0; break; case BTC_WLACT_SW_LO: - dm->gnt.bt[i].wlan_act_en = 1; - dm->gnt.bt[i].wlan_act = 0; + b[i].wlan_act_en = 1; + b[i].wlan_act = 0; break; case BTC_WLACT_SW_HI: - dm->gnt.bt[i].wlan_act_en = 1; - dm->gnt.bt[i].wlan_act = 1; + b[i].wlan_act_en = 1; + b[i].wlan_act = 1; break; } } } - rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt); + + if (!btc->ver->fcxosi) { + rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt); + return; + } + + memcpy(osi->gnt_set, dm->gnt.band, sizeof(osi->gnt_set)); + memcpy(osi->wlact_set, dm->gnt.bt, sizeof(osi->wlact_set)); + + /* GBT source should be GBT_S1 in 1+1 (HWB0:5G + HWB1:2G) case */ + if (osi->rf_band[BTC_RF_S0] == 1 && + osi->rf_band[BTC_RF_S1] == 0) + osi->rf_gbt_source = BTC_RF_S1; + else + osi->rf_gbt_source = BTC_RF_S0; } #define BTC_TDMA_WLROLE_MAX 3 @@ -3062,7 +3241,7 @@ static void _update_btc_state_map(struct rtw89_dev *rtwdev) } } -static void _set_bt_afh_info(struct rtw89_dev *rtwdev) +static void _set_bt_afh_info_v0(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_btc *btc = &rtwdev->btc; @@ -3231,6 +3410,115 @@ static void _set_bt_afh_info(struct rtw89_dev *rtwdev) btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; } +static void _set_bt_afh_info_v1(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; + struct rtw89_btc_wl_afh_info *wl_afh = &wl->afh_info; + struct rtw89_btc_bt_info *bt = &btc->cx.bt; + struct rtw89_btc_wl_rlink *rlink; + u8 en = 0, ch = 0, bw = 0, buf[3] = {}; + u8 i, j, link_mode; + + if (btc->manual_ctrl || wl->status.map.scan) + return; + + link_mode = wl_rinfo->link_mode; + + for (i = 0; i < btc->ver->max_role_num; i++) { + for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) { + if (wl->status.map.rf_off || bt->whql_test || + link_mode == BTC_WLINK_NOLINK || + link_mode == BTC_WLINK_5G) + break; + + rlink = &wl_rinfo->rlink[i][j]; + + /* Don't care no-connected/non-2G-band role */ + if (!rlink->connected || !rlink->active || + rlink->rf_band != RTW89_BAND_2G) + continue; + + en = 1; + ch = rlink->ch; + bw = rlink->bw; + + if (link_mode == BTC_WLINK_2G_MCC && + (rlink->role == RTW89_WIFI_ROLE_AP || + rlink->role == RTW89_WIFI_ROLE_P2P_GO || + rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { + /* for 2.4G MCC, take role = ap/go/gc */ + break; + } else if (link_mode != BTC_WLINK_2G_SCC || + rlink->bw == RTW89_CHANNEL_WIDTH_40) { + /* for 2.4G scc, take bw = 40M */ + break; + } + } + } + + /* default AFH channel sapn = center-ch +- 6MHz */ + switch (bw) { + case RTW89_CHANNEL_WIDTH_20: + if (btc->dm.freerun || btc->dm.fddt_train) + bw = 48; + else + bw = 20 + chip->afh_guard_ch * 2; + break; + case RTW89_CHANNEL_WIDTH_40: + if (btc->dm.freerun) + bw = 40 + chip->afh_guard_ch * 2; + else + bw = 40; + break; + case RTW89_CHANNEL_WIDTH_5: + bw = 5 + chip->afh_guard_ch * 2; + break; + case RTW89_CHANNEL_WIDTH_10: + bw = 10 + chip->afh_guard_ch * 2; + break; + default: + en = false; /* turn off AFH info if invalid BW */ + bw = 0; + ch = 0; + break; + } + + if (!en || ch > 14 || ch == 0) { + en = false; + bw = 0; + ch = 0; + } + + if (wl_afh->en == en && + wl_afh->ch == ch && + wl_afh->bw == bw && + (!bt->enable.now || bt->enable.last)) + return; + + wl_afh->en = buf[0]; + wl_afh->ch = buf[1]; + wl_afh->bw = buf[2]; + + if (_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3)) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): en=%d, ch=%d, bw=%d\n", + __func__, en, ch, bw); + + btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; + } +} + +static void _set_bt_afh_info(struct rtw89_dev *rtwdev) +{ + if (rtwdev->chip->chip_id == RTL8922A) + _set_bt_afh_info_v1(rtwdev); + else + _set_bt_afh_info_v0(rtwdev); +} + static bool _check_freerun(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -3716,6 +4004,15 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) u32 tbl_w1, tbl_b1, tbl_b4; u16 dur_2; + if (wl->status.map.lps) { + _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, + s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); + _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_EBT, s_def[CXST_EBT].dur, + s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); + } + type = FIELD_GET(BTC_CXP_MASK, policy_type); if (btc->ant_type == BTC_ANT_SHARED) { @@ -3836,13 +4133,13 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) switch (policy_type) { case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */ - _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_ISO); + _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO); _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); _slot_set_dur(btc, CXST_EBT, dur_2); break; case BTC_CXP_OFFE_2GISOB: /* for bt no-link */ - _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_ISO); + _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO); _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); _slot_set_dur(btc, CXST_EBT, dur_2); @@ -3868,15 +4165,15 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) break; case BTC_CXP_OFFE_2GBWMIXB: if (a2dp->exist) - _slot_set(btc, CXST_E2G, 0, cxtbl[2], SLOT_MIX); + _slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX); else - _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_MIX); - _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, + _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX); + _slot_set_le(btc, CXST_EBT, cpu_to_le16(40), 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); - _slot_set(btc, CXST_EBT, 0, cxtbl[1], SLOT_MIX); + _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX); + _slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX); break; default: break; @@ -4864,16 +5161,14 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev) struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; + struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info; - struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_bt_info *bt = &btc->cx.bt; struct rtw89_btc_dm *dm = &btc->dm; struct _wl_rinfo_now wl_rinfo; - u32 run_reason = btc->dm.run_reason; - u32 is_btg; - u8 i, val; + u32 is_btg = BTC_BTGCTRL_DISABLE; if (btc->manual_ctrl) return; @@ -4891,63 +5186,62 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev) else return; - if (rtwdev->dbcc_en) { - if (ver->fwlrole == 0) { - wl_rinfo.dbcc_2g_phy = RTW89_PHY_NUM; + /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ + if (btc->ant_type == BTC_ANT_SHARED) { + if (!(bt->run_patch_code && bt->enable.now)) + is_btg = BTC_BTGCTRL_DISABLE; + else if (wl_rinfo.link_mode != BTC_WLINK_5G) + is_btg = BTC_BTGCTRL_ENABLE; + else + is_btg = BTC_BTGCTRL_DISABLE; - for (i = 0; i < RTW89_PHY_NUM; i++) { - if (wl_dinfo->real_band[i] == RTW89_BAND_2G) - wl_rinfo.dbcc_2g_phy = i; - } - } else if (ver->fwlrole == 1) { - wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy; - } else if (ver->fwlrole == 2) { - wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy; - } else if (ver->fwlrole == 7) { - wl_rinfo.dbcc_2g_phy = wl_rinfo_v7->dbcc_2g_phy; - } else if (ver->fwlrole == 8) { - wl_rinfo.dbcc_2g_phy = wl_rinfo_v8->dbcc_2g_phy; - } else { - return; - } + /* bb call ctrl_btg() in WL FW by slot */ + if (!ver->fcxosi && + wl_rinfo.link_mode == BTC_WLINK_25G_MCC) + is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; } - if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC) - is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; - else if (!(bt->run_patch_code && bt->enable.now)) - is_btg = BTC_BTGCTRL_DISABLE; - else if (wl_rinfo.link_mode == BTC_WLINK_5G) - is_btg = BTC_BTGCTRL_DISABLE; - else if (dm->freerun) - is_btg = BTC_BTGCTRL_DISABLE; - else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1) - is_btg = BTC_BTGCTRL_DISABLE; + if (is_btg == dm->wl_btg_rx) + return; else - is_btg = BTC_BTGCTRL_ENABLE; + dm->wl_btg_rx = is_btg; - if (dm->wl_btg_rx_rb != dm->wl_btg_rx && - dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) { - _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val); - dm->wl_btg_rx_rb = val; - } + /* skip setup if btg_ctrl set by wl fw */ + if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE) + return; - if (run_reason == BTC_RSN_NTFY_INIT || - run_reason == BTC_RSN_NTFY_SWBAND || - dm->wl_btg_rx_rb != dm->wl_btg_rx || - is_btg != dm->wl_btg_rx) { + /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */ + if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ + if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ + o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE; + else + o_info->btg_rx[BTC_RF_S0] = is_btg; - dm->wl_btg_rx = is_btg; + if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ + o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE; + else + o_info->btg_rx[BTC_RF_S1] = is_btg; + } else { /* 2+0 or 0+2 */ + o_info->btg_rx[BTC_RF_S0] = is_btg; + o_info->btg_rx[BTC_RF_S1] = is_btg; + } - if (is_btg > BTC_BTGCTRL_ENABLE) - return; + if (ver->fcxosi) + return; - chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0); - } + chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0], + RTW89_PHY_0); + if (chip->chip_id != RTL8922A) + return; + + chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1], + RTW89_PHY_1); } static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2; @@ -4979,9 +5273,7 @@ static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) return; } - if (link_mode == BTC_WLINK_25G_MCC) { - is_preagc = BTC_PREAGC_BB_FWCTRL; - } else if (!(bt->run_patch_code && bt->enable.now)) { + if (!(bt->run_patch_code && bt->enable.now)) { is_preagc = BTC_PREAGC_DISABLE; } else if (link_mode == BTC_WLINK_5G) { is_preagc = BTC_PREAGC_DISABLE; @@ -5001,6 +5293,9 @@ static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) is_preagc = BTC_PREAGC_ENABLE; } + if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC) + is_preagc = BTC_PREAGC_BB_FWCTRL; + if (dm->wl_pre_agc_rb != dm->wl_pre_agc && dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); @@ -5014,9 +5309,34 @@ static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) is_preagc != dm->wl_pre_agc) { dm->wl_pre_agc = is_preagc; - if (is_preagc > BTC_PREAGC_ENABLE) + if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE) return; - chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0); + + if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ + if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ + o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE; + else + o_info->nbtg_tx[BTC_RF_S0] = is_preagc; + + if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ + o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE; + else + o_info->nbtg_tx[BTC_RF_S1] = is_preagc; + + } else { /* 2+0 or 0+2 */ + o_info->nbtg_tx[BTC_RF_S0] = is_preagc; + o_info->nbtg_tx[BTC_RF_S1] = is_preagc; + } + + if (btc->ver->fcxosi) + return; + + chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0], + RTW89_PHY_0); + if (chip->chip_id != RTL8922A) + return; + chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1], + RTW89_PHY_1); } } @@ -5229,15 +5549,47 @@ static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); } +static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_dm *dm = &btc->dm; + u32 add; + + if (mac == wl->pta_req_mac) + return; + + dm->ost_info.pta_req_hw_band = mac; + wl->pta_req_mac = mac; + wl->pta_reg_mac_chg = true; + + if (btc->ver->fcxosi) + return; + + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + add = R_BE_BTC_CFG; + else + add = R_AX_BTC_CFG; + + if (mac == RTW89_MAC_0) + rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC); + else + rtw89_write32_set(rtwdev, add, B_AX_WL_SRC); +} + static void _action_common(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; struct rtw89_btc_bt_info *bt = &btc->cx.bt; struct rtw89_btc_dm *dm = &btc->dm; u32 bt_rom_code_id, bt_fw_ver; + if (btc->ver->fwlrole == 8) + _wl_req_mac(rtwdev, rinfo_v8->pta_req_band); + _set_btg_ctrl(rtwdev); _set_wl_preagc_ctrl(rtwdev); _set_wl_tx_limit(rtwdev); @@ -5273,7 +5625,18 @@ static void _action_common(struct rtw89_dev *rtwdev) wl->scbd_change = false; btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; } + + if (btc->ver->fcxosi) { + if (memcmp(&dm->ost_info_last, &dm->ost_info, + sizeof(dm->ost_info_last)) || + dm->run_reason == BTC_RSN_NTFY_INIT || + dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) { + dm->ost_info_last = dm->ost_info; + _fw_set_drv_info(rtwdev, CXDRVINFO_OSI); + } + } btc->dm.tdma_instant_excute = 0; + wl->pta_reg_mac_chg = false; } static void _action_by_bt(struct rtw89_dev *rtwdev) @@ -5736,14 +6099,6 @@ _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) return next_state; } -static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) -{ - if (mac == RTW89_MAC_0) - rtw89_write32_clr(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC); - else - rtw89_write32_set(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC); -} - static void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -6239,23 +6594,16 @@ static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1, } static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, - u8 *phy, u8 *role, u8 *dbcc_2g_phy) + u8 *phy, u8 *role, u8 link_cnt) { struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false; - u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, connect_cnt; - - if (rtwdev->btc.ver->fwlrole == 7) - connect_cnt = rinfo_v7->connect_cnt; - else if (rtwdev->btc.ver->fwlrole == 8) - connect_cnt = rinfo_v8->connect_cnt; - else - return BTC_WLINK_NOLINK; + u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band; /* find out the 2G-PHY by connect-id ->ch */ - for (j = 0; j < connect_cnt; j++) { + for (j = 0; j < link_cnt; j++) { if (ch[j].center_ch <= 14) { is_2g_ch_exist = true; break; @@ -6264,21 +6612,33 @@ static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, /* If no any 2G-port exist, it's impossible because 5G-exclude */ if (!is_2g_ch_exist) - return BTC_WLINK_OTHER; + return BTC_WLINK_5G; dbcc_2g_cid = j; - *dbcc_2g_phy = phy[dbcc_2g_cid]; + dbcc_2g_phy = phy[dbcc_2g_cid]; + + if (dbcc_2g_phy == RTW89_PHY_1) + pta_req_band = RTW89_PHY_1; + else + pta_req_band = RTW89_PHY_0; + + if (rtwdev->btc.ver->fwlrole == 7) { + rinfo_v7->dbcc_2g_phy = dbcc_2g_phy; + } else if (rtwdev->btc.ver->fwlrole == 8) { + rinfo_v8->dbcc_2g_phy = dbcc_2g_phy; + rinfo_v8->pta_req_band = pta_req_band; + } /* connect_cnt <= 2 */ - if (connect_cnt < BTC_TDMA_WLROLE_MAX) + if (link_cnt < BTC_TDMA_WLROLE_MAX) return (_get_role_link_mode((role[dbcc_2g_cid]))); /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */ - for (k = 0; k < connect_cnt; k++) { + for (k = 0; k < link_cnt; k++) { if (k == dbcc_2g_cid) continue; - if (phy[k] == *dbcc_2g_phy) { + if (phy[k] == dbcc_2g_phy) { is_multi_role_in_2g_phy = true; dbcc_2g_cid2 = k; break; @@ -6480,7 +6840,7 @@ static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid) } else if (cnt > BTC_TDMA_WLROLE_MAX) { mode = BTC_WLINK_OTHER; } else if (rtwdev->dbcc_en) { - mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, &dbcc_2g_phy); + mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); /* correct 2G-located PHY band for gnt ctrl */ if (dbcc_2g_phy < RTW89_PHY_NUM) @@ -6525,26 +6885,336 @@ static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid) _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); } +static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type) +{ + struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; + struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; + u8 mode = BTC_WLINK_NOLINK; + + switch (type) { + case RTW89_MR_WTYPE_NONE: /* no-link */ + mode = BTC_WLINK_NOLINK; + break; + case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */ + case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */ + if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { + mode = BTC_WLINK_5G; + } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { + mode = BTC_WLINK_2G_GO; + } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) { + if (wl->role_info_v8.p2p_2g) + mode = BTC_WLINK_2G_GC; + else + mode = BTC_WLINK_2G_STA; + } + break; + case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */ + case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */ + if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { + mode = BTC_WLINK_5G; + } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ || + mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) { + mode = BTC_WLINK_25G_MCC; + } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) { + mode = BTC_WLINK_2G_MCC; + } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) { + mode = BTC_WLINK_2G_SCC; + } + break; + case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */ + if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) + mode = BTC_WLINK_5G; + else if (wl->role_info_v8.p2p_2g) + mode = BTC_WLINK_2G_GC; + else + mode = BTC_WLINK_2G_STA; + break; + case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */ + case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */ + /* driver may doze 1-link to + * 2G+5G -> TDMA slot switch by E2G/E5G + * 5G only -> TDMA slot switch by E5G + */ + mode = BTC_WLINK_25G_MCC; + break; + case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */ + if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { + mode = BTC_WLINK_5G; + } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { + mode = BTC_WLINK_2G_GO; + } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) { + if (wl->role_info_v8.p2p_2g) + mode = BTC_WLINK_2G_GC; + else + mode = BTC_WLINK_2G_STA; + } + break; + } + return mode; +} + +static void _update_wl_mlo_info(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; + struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; + struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; + struct rtw89_mr_chanctx_info qinfo; + u8 track_band = RTW89_PHY_0; + u8 rf_band = RTW89_BAND_2G; + u8 i, type; + + /* parse MLO info form PHL API for each HW-band */ + for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { + memset(&qinfo, 0, sizeof(qinfo)); + + rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo); + mlo_info->wmode[i] = qinfo.wmode; + mlo_info->ch_type[i] = qinfo.ctxtype; + mlo_info->wtype = qinfo.wtype; + + if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ || + mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ || + mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ) + mlo_info->hwb_rf_band[i] = RTW89_BAND_5G; + else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ || + mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ) + mlo_info->hwb_rf_band[i] = RTW89_BAND_6G; + else /* check if "2G-included" or unknown in each HW-band */ + mlo_info->hwb_rf_band[i] = RTW89_BAND_2G; + } + + mlo_info->link_status = rtwdev->mlo_dbcc_mode; + type = mlo_info->wtype; + + if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R || + mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R || + mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R || + mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD || + mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD || + mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD) + mlo_info->mlo_en = 1; + else + mlo_info->mlo_en = 0; + + if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE && + mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN && + mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE && + mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN) + mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */ + else + mlo_info->dual_hw_band_en = 0; + + if (mlo_info->link_status == MLO_2_PLUS_0_2RF || + mlo_info->link_status == MLO_0_PLUS_2_2RF || + mlo_info->link_status == MLO_2_PLUS_2_2RF) + mlo_info->mlo_adie = 2; + else + mlo_info->mlo_adie = 1; + + switch (mlo_info->link_status) { + default: + case MLO_2_PLUS_0_1RF: /* 2+0 */ + case MLO_2_PLUS_0_2RF: + mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0; + track_band = RTW89_MAC_0; + rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0]; + mlo_info->path_rf_band[BTC_RF_S0] = rf_band; + mlo_info->path_rf_band[BTC_RF_S1] = rf_band; + + wl_rinfo->pta_req_band = RTW89_MAC_0; + wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; + wl_rinfo->dbcc_en = 0; + break; + case MLO_0_PLUS_2_1RF: /* 0+2 */ + case MLO_0_PLUS_2_2RF: + mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2; + track_band = RTW89_MAC_1; + rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1]; + mlo_info->path_rf_band[BTC_RF_S0] = rf_band; + mlo_info->path_rf_band[BTC_RF_S1] = rf_band; + + wl_rinfo->pta_req_band = RTW89_MAC_1; + wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; + wl_rinfo->dbcc_en = 0; + break; + case MLO_1_PLUS_1_1RF: /* 1+1 */ + case MLO_1_PLUS_1_2RF: /* 1+1 */ + case MLO_2_PLUS_2_2RF: /* 2+2 */ + case DBCC_LEGACY: /* DBCC 1+1 */ + if (mlo_info->link_status == MLO_2_PLUS_2_2RF) + mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2; + else + mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1; + + if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) + track_band = RTW89_MAC_0; + else + track_band = RTW89_MAC_1; + + mlo_info->path_rf_band[BTC_RF_S0] = + mlo_info->hwb_rf_band[RTW89_MAC_0]; + mlo_info->path_rf_band[BTC_RF_S1] = + mlo_info->hwb_rf_band[RTW89_MAC_1]; + + /* Check ch count from ch_type @ 2.4G HW-band, and modify type */ + if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ) + type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */ + else + type = RTW89_MR_WTYPE_NONMLD_NONMLD; + + if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) { + wl_rinfo->pta_req_band = RTW89_MAC_0; + wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; + } else { + wl_rinfo->pta_req_band = RTW89_MAC_1; + wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; + } + + if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE && + mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE) + wl_rinfo->dbcc_en = 0; + else + wl_rinfo->dbcc_en = 1; + break; + } + + wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type); + + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d", + __func__, id_to_linkmode(wl_rinfo->link_mode), + wl_rinfo->pta_req_band); +} + +static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; + struct rtw89_btc_wl_rlink *rlink = NULL; + struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; + struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; + u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; + u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; + bool b2g = false, b5g = false, outloop = false; + u8 mode = BTC_WLINK_NOLINK; + u8 cnt_2g = 0, cnt_5g = 0; + u8 i, j, cnt = 0; + + for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) { + for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { + rlink = &wl_rinfo->rlink[i][j]; + + if (!rlink->active || !rlink->connected) + continue; + + if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) { + outloop = true; + break; + } + + cid_ch[cnt] = wl->rlink_info[i][j].chdef; + cid_phy[cnt] = rlink->phy; + cid_role[cnt] = rlink->role; + cnt++; + + if (rlink->rf_band != RTW89_BAND_2G) { + cnt_5g++; + b5g = true; + } else { + cnt_2g++; + b2g = true; + } + } + if (outloop) + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g); + + wl_rinfo->dbcc_en = rtwdev->dbcc_en; + /* Be careful to change the following sequence!! */ + if (cnt == 0) { + mode = BTC_WLINK_NOLINK; + } else if (!b2g && b5g) { + mode = BTC_WLINK_5G; + } else if (wl_rinfo->dbcc_en) { + mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); + } else if (b2g && b5g) { + mode = BTC_WLINK_25G_MCC; + } else if (!b5g && cnt >= 2) { + if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1])) + mode = BTC_WLINK_2G_SCC; + else + mode = BTC_WLINK_2G_MCC; + } else if (!b5g) { /* cnt_connect = 1 */ + mode = _get_role_link_mode(cid_role[0]); + } + + wl_rinfo->link_mode = mode; +} + +static void _modify_role_link_mode(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; + struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; + u8 go_cleint_exist = wl->go_client_exist; + u8 link_mode = wl_rinfo->link_mode; + u32 role_map = wl_rinfo->role_map; + u8 noa_exist = wl->noa_exist; + u32 mrole = BTC_WLMROLE_NONE; + + /* if no client_joined, don't care P2P-GO/AP role */ + if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || + (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) { + if (link_mode == BTC_WLINK_2G_SCC) { + wl_rinfo->link_mode = BTC_WLINK_2G_STA; + } else if (link_mode == BTC_WLINK_2G_GO || + link_mode == BTC_WLINK_2G_AP) { + wl_rinfo->link_mode = BTC_WLINK_NOLINK; + } + } + + /* Identify 2-Role type */ + if (link_mode == BTC_WLINK_2G_SCC || + link_mode == BTC_WLINK_2G_MCC || + link_mode == BTC_WLINK_25G_MCC || + link_mode == BTC_WLINK_5G) { + if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || + (role_map & BIT(RTW89_WIFI_ROLE_AP))) { + if (noa_exist) + mrole = BTC_WLMROLE_STA_GO_NOA; + else + mrole = BTC_WLMROLE_STA_GO; + } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) { + if (noa_exist) + mrole = BTC_WLMROLE_STA_GC_NOA; + else + mrole = BTC_WLMROLE_STA_GC; + } else { + mrole = BTC_WLMROLE_STA_STA; + } + } + + wl_rinfo->mrole_type = mrole; + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__, + id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type); +} + static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id, enum btc_role_state state) { + struct rtw89_btc_wl_rlink *rlink = NULL; + struct rtw89_btc_wl_link_info *wl_linfo; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_wl_info *wl = &btc->cx.wl; - struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER]; struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; - struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; - bool client_joined = false, b2g = false, b5g = false; - u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; - u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; - u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0; - u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0; - struct rtw89_btc_wl_link_info *wl_linfo; - struct rtw89_btc_wl_rlink *rlink = NULL; - u8 dbcc_2g_phy = RTW89_PHY_0; - u8 mode = BTC_WLINK_NOLINK; - u32 noa_dur = 0; + bool client_joined = false, noa_exist = false, p2p_exist = false; + bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori; + u8 i, j, link_mode_ori; + u32 role_map = 0; - if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1) + if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM) return; /* Extract wl->link_info[role_id][rlink_id] to wl->role_info @@ -6554,10 +7224,8 @@ static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id */ wl_linfo = &wl->rlink_info[role_id][rlink_id]; - if (wl_linfo->connected == MLME_LINKING) - return; - rlink = &wl_rinfo->rlink[role_id][rlink_id]; + rlink->role = wl_linfo->role; rlink->active = wl_linfo->active; /* Doze or not */ rlink->pid = wl_linfo->pid; @@ -6573,8 +7241,6 @@ static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id switch (wl_linfo->connected) { case MLME_NO_LINK: rlink->connected = 0; - if (rlink->role == RTW89_WIFI_ROLE_STATION) - btc->dm.leak_ap = 0; break; case MLME_LINKED: rlink->connected = 1; @@ -6583,130 +7249,72 @@ static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id return; } - wl->is_5g_hi_channel = false; - wl->bg_mode = false; - wl_rinfo->role_map = 0; - wl_rinfo->p2p_2g = 0; - memset(cid_ch, 0, sizeof(cid_ch)); - - for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { - for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) { + for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) { + for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { rlink = &wl_rinfo->rlink[i][j]; if (!rlink->active || !rlink->connected) continue; - cnt++; - wl_rinfo->role_map |= BIT(rlink->role); - - /* only if client connect for p2p-Go/AP */ - if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO || - rlink->role == RTW89_WIFI_ROLE_AP) && - rlink->client_cnt > 1) - client_joined = true; - - /* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/ - if (rlink->rf_band == RTW89_BAND_2G && - (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) - wl_rinfo->p2p_2g = 1; + role_map |= BIT(rlink->role); /* only one noa-role exist */ if (rlink->noa && rlink->noa_dur > 0) - noa_dur = rlink->noa_dur; + noa_exist = true; /* for WL 5G-Rx interfered with BT issue */ - if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100) - wl->is_5g_hi_channel = 1; - - if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || - (rlink->mode & BIT(BTC_WL_MODE_11G))) - wl->bg_mode = 1; + if (rlink->rf_band == RTW89_BAND_5G) { + if (rlink->ch >= 100) + is_5g_hi_channel = true; - if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) continue; + } - cid_ch[cnt - 1] = wl_linfo->chdef; - cid_phy[cnt - 1] = rlink->phy; - cid_role[cnt - 1] = rlink->role; - - if (rlink->rf_band != RTW89_BAND_2G) { - cnt_5g++; - b5g = true; - } else { - cnt_2g++; - b2g = true; + /* only if client connect for p2p-Go/AP */ + if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO || + rlink->role == RTW89_WIFI_ROLE_AP) && + rlink->client_cnt > 1) { + p2p_exist = true; + client_joined = true; } - } - } - if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { - rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g); - rtw89_warn(rtwdev, "not support MLO feature yet"); - } else { - dbcc_en = rtwdev->dbcc_en; + /* Identify if P2P-Go (GO/GC/AP) exist at 2G band */ + if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT) + p2p_exist = true; - /* Be careful to change the following sequence!! */ - if (cnt == 0) { - mode = BTC_WLINK_NOLINK; - } else if (!b2g && b5g) { - mode = BTC_WLINK_5G; - } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) { - mode = BTC_WLINK_2G_NAN; - } else if (cnt > BTC_TDMA_WLROLE_MAX) { - mode = BTC_WLINK_OTHER; - } else if (dbcc_en) { - mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, - &dbcc_2g_phy); - } else if (b2g && b5g && cnt == 2) { - mode = BTC_WLINK_25G_MCC; - } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */ - if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1])) - mode = BTC_WLINK_2G_SCC; - else - mode = BTC_WLINK_2G_MCC; - } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */ - mode = _get_role_link_mode(cid_role[0]); + if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || + (rlink->mode & BIT(BTC_WL_MODE_11G))) + bg_mode = true; } } - wl_rinfo->link_mode = mode; - wl_rinfo->connect_cnt = cnt; - if (wl_rinfo->connect_cnt == 0) - wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE); - _update_role_link_mode(rtwdev, client_joined, noa_dur); + link_mode_ori = wl_rinfo->link_mode; + wl->is_5g_hi_channel = is_5g_hi_channel; + wl->bg_mode = bg_mode; + wl->go_client_exist = client_joined; + wl->noa_exist = noa_exist; + wl_rinfo->p2p_2g = p2p_exist; + wl_rinfo->role_map = role_map; - wl_rinfo->dbcc_2g_phy = dbcc_2g_phy; - if (wl_rinfo->dbcc_en != dbcc_en) { - wl_rinfo->dbcc_en = dbcc_en; - wl_rinfo->dbcc_chg = 1; - btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; + dbcc_en_ori = wl_rinfo->dbcc_en; + + if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { + /* for MLO-supported, link-mode from driver directly */ + _update_wl_mlo_info(rtwdev); } else { - wl_rinfo->dbcc_chg = 0; + /* for non-MLO-supported, link-mode by BTC */ + _update_wl_non_mlo_info(rtwdev); } - if (wl_rinfo->dbcc_en) { - memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info)); + _modify_role_link_mode(rtwdev); - if (mode == BTC_WLINK_5G) { - pta_req_band = RTW89_PHY_0; - wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G; - wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G; - } else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) { - pta_req_band = RTW89_PHY_1; - wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G; - wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G; - } else { - pta_req_band = RTW89_PHY_0; - wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G; - wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G; - } - _update_dbcc_band(rtwdev, RTW89_PHY_0); - _update_dbcc_band(rtwdev, RTW89_PHY_1); - } + if (link_mode_ori != wl_rinfo->link_mode) + wl->link_mode_chg = true; - wl_rinfo->pta_req_band = pta_req_band; - _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); + if (wl_rinfo->dbcc_en != dbcc_en_ori) { + wl->dbcc_chg = true; + btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; + } } void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work) @@ -6829,12 +7437,33 @@ static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); + if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE)) + status_change = true; bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); if (!only_update && status_change) _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); } +#define BTC_BTINFO_PWR_LEN 5 +static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) +{ + struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt; + struct rtw89_btc_bt_link_info *b = &bt->link_info; + + if (len != BTC_BTINFO_PWR_LEN) + return; + + if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s return by info duplicate!\n", __func__); + return; + } + + memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX); + memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc)); +} + static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -7618,7 +8247,6 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, wlinfo = &wl->link_info[r.pid]; - rlink_id = 0; /* to do */ if (ver->fwlrole == 0) { *wlinfo = r; _update_wl_info(rtwdev); @@ -7632,6 +8260,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, *wlinfo = r; _update_wl_info_v7(rtwdev, r.pid); } else if (ver->fwlrole == 8) { + rlink_id = rtwvif_link->mac_idx; wlinfo = &wl->rlink_info[r.pid][rlink_id]; *wlinfo = r; link_mode_ori = wl->role_info_v8.link_mode; @@ -7876,7 +8505,11 @@ void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, 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]; + if (btc->ver->fwlrole != 8) + link_info = &wl->link_info[port]; + else + link_info = &wl->rlink_info[port][rtwvif_link->mac_idx]; + link_info->stat.traffic = *stats; link_info_t = &link_info->stat.traffic; @@ -7957,13 +8590,12 @@ void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; 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_link->ra_report.hw_rate; - dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; } + dm->trx_info.tx_lvl = stats->tx_tfc_lv; + dm->trx_info.rx_lvl = stats->rx_tfc_lv; + 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; dm->trx_info.rx_tp = link_info_t->rx_throughput; @@ -8070,6 +8702,8 @@ static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) return BTF_EVNT_BUF_OVERFLOW; else if (ver->fwc2hfunc == 2) return func; + else if (ver->fwc2hfunc == 3) + return BTF_EVNT_BUF_OVERFLOW; else return BTF_EVNT_MAX; case BTF_EVNT_BUF_OVERFLOW: @@ -8079,11 +8713,20 @@ static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) return BTF_EVNT_C2H_LOOPBACK; else if (ver->fwc2hfunc == 2) return func; + else if (ver->fwc2hfunc == 3) + return BTF_EVNT_C2H_LOOPBACK; else return BTF_EVNT_MAX; case BTF_EVNT_C2H_LOOPBACK: if (ver->fwc2hfunc == 2) return func; + else if (ver->fwc2hfunc == 3) + return BTF_EVNT_BT_LEAUDIO_INFO; + else + return BTF_EVNT_MAX; + case BTF_EVNT_BT_QUERY_TXPWR: + if (ver->fwc2hfunc == 3) + return func; else return BTF_EVNT_MAX; case BTF_EVNT_MAX: @@ -8146,6 +8789,9 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, case BTF_EVNT_CX_RUNINFO: btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; break; + case BTF_EVNT_BT_QUERY_TXPWR: + btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++; + _update_bt_txpwr_info(rtwdev, buf, len); } } @@ -8168,11 +8814,9 @@ static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) return 0; - dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; - p += scnprintf(p, end - p, - "========== [BTC COEX INFO (%d)] ==========\n", - chip->chip_id); + "\n========== [BTC COEX INFO (%s)] ==========\n", + chip_id_str(chip->chip_id)); ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); @@ -8198,8 +8842,8 @@ static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n", bt->ver_info.fw_coex, - (bt->ver_info.fw_coex >= chip->btcx_desired ? - "Match" : "Mismatch"), chip->btcx_desired); + (bt->ver_info.fw_coex >= ver->bt_desired ? + "Match" : "Mismatch"), ver->bt_desired); if (bt->enable.now && bt->ver_info.fw == 0) rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); @@ -8248,65 +8892,52 @@ static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_wl_link_info *plink = NULL; - struct rtw89_btc_wl_info *wl = &btc->cx.wl; - struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; struct rtw89_traffic_stats *t; char *p = buf, *end = buf + bufsz; - u8 i; - - if (rtwdev->dbcc_en) { - p += scnprintf(p, end - p, - " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", - "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], - wl_dinfo->scan_band[RTW89_PHY_0], - wl_dinfo->real_band[RTW89_PHY_0]); - p += scnprintf(p, end - p, - "PHY1_band(op:%d/scan:%d/real:%d)\n", - wl_dinfo->op_band[RTW89_PHY_1], - wl_dinfo->scan_band[RTW89_PHY_1], - wl_dinfo->real_band[RTW89_PHY_1]); - } + u8 i, j; - for (i = 0; i < RTW89_PORT_NUM; i++) { - if (btc->ver->fwlrole == 8) - plink = &btc->cx.wl.rlink_info[i][0]; - else - plink = &btc->cx.wl.link_info[i]; + for (i = 0; i < btc->ver->max_role_num; i++) { + for (j = 0; j < RTW89_MAC_NUM; j++) { + if (btc->ver->fwlrole == 8) + plink = &btc->cx.wl.rlink_info[i][j]; + else + plink = &btc->cx.wl.link_info[i]; - if (!plink->active) - continue; + if (!plink->active) + continue; - p += scnprintf(p, end - p, - " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", - plink->pid, (u32)plink->role, plink->phy, - (u32)plink->connected, plink->client_cnt - 1, - (u32)plink->mode, plink->ch, (u32)plink->bw); + p += scnprintf(p, end - p, + " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", + plink->pid, plink->role, plink->phy, + id_to_mlme_state(plink->connected), + plink->client_cnt - 1, plink->mode, + plink->ch, plink->bw); - if (plink->connected == MLME_NO_LINK) - continue; + if (plink->connected == MLME_NO_LINK) + continue; - p += scnprintf(p, end - p, - ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", - plink->mac_id, plink->tx_time, plink->tx_retry); + p += scnprintf(p, end - p, + ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", + plink->mac_id, plink->tx_time, plink->tx_retry); - p += scnprintf(p, end - p, - " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", - plink->pid, 110 - plink->stat.rssi, - plink->stat.rssi, plink->busy, - plink->dir == RTW89_TFC_UL ? "UL" : "DL"); + p += scnprintf(p, end - p, + " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", + plink->pid, 110 - plink->stat.rssi, + plink->stat.rssi, plink->busy, + plink->dir == RTW89_TFC_UL ? "UL" : "DL"); - t = &plink->stat.traffic; + t = &plink->stat.traffic; - p += scnprintf(p, end - p, - "tx[rate:%d/busy_level:%d], ", - (u32)t->tx_rate, t->tx_tfc_lv); + p += scnprintf(p, end - p, + "tx[rate:%d/busy_level:%d], ", + t->tx_rate, t->tx_tfc_lv); - p += scnprintf(p, end - p, - "rx[rate:%d/busy_level:%d/drop:%d]\n", - (u32)t->rx_rate, - t->rx_tfc_lv, plink->rx_rate_drop_cnt); + p += scnprintf(p, end - p, + "rx[rate:%d/busy_level:%d/drop:%d]\n", + t->rx_rate, + t->rx_tfc_lv, plink->rx_rate_drop_cnt); + } } - return p - buf; } @@ -8342,8 +8973,8 @@ static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) else goto out; - p += scnprintf(p, end - p, " %-15s : link_mode:%d, ", "[status]", - mode); + p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]", + id_to_linkmode(mode)); p += scnprintf(p, end - p, "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", @@ -8433,8 +9064,11 @@ static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) struct rtw89_btc_cx *cx = &btc->cx; struct rtw89_btc_bt_info *bt = &cx->bt; struct rtw89_btc_wl_info *wl = &cx->wl; + u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; union rtw89_btc_module_info *md = &btc->mdinfo; + s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm; + s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm; char *p = buf, *end = buf + bufsz; u8 *afh = bt_linfo->afh_map; u8 *afh_le = bt_linfo->afh_map_le; @@ -8567,6 +9201,28 @@ static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, "\n"); } + if (ver_main >= 9 && bt_linfo->profile_cnt.now) + rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true); + else + rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false); + + if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) { + p += scnprintf(p, end - p, + " %-15s : br_index:0x%x, le_index:0x%x", + "[bt_txpwr_lvl]", + bt->link_info.bt_txpwr_desc.br_gain_index, + bt->link_info.bt_txpwr_desc.le_gain_index); + p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm); + p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm); + } else { + p += scnprintf(p, end - p, + " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]", + "[bt_txpwr_lvl]", + bt->link_info.bt_txpwr_desc.br_dbm, + bt->link_info.bt_txpwr_desc.le_dbm); + } + p += scnprintf(p, end - p, "\n"); + if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect) rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true); else @@ -9142,7 +9798,6 @@ static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) if (i % 5 == 4) p += scnprintf(p, end - p, "\n"); } - p += scnprintf(p, end - p, "\n"); return p - buf; } @@ -9714,7 +10369,7 @@ static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz return 0; pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7; - p += scnprintf(p, end - p, "\n\r %-15s : cycle:%d", "[slot_stat]", + p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]", le16_to_cpu(pcysta->cycles)); for (i = 0; i < CXST_MAX; i++) { @@ -9862,7 +10517,7 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) ns = &pfwinfo->rpt_fbtc_nullsta.finfo; if (ver->fcxnullsta == 1) { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); + p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[ok:%d/", le32_to_cpu(ns->v1.result[i][1])); @@ -9875,13 +10530,13 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, "avg_t:%d.%03d/", le32_to_cpu(ns->v1.avg_t[i]) / 1000, le32_to_cpu(ns->v1.avg_t[i]) % 1000); - p += scnprintf(p, end - p, "max_t:%d.%03d]\n", + p += scnprintf(p, end - p, "max_t:%d.%03d]", le32_to_cpu(ns->v1.max_t[i]) / 1000, le32_to_cpu(ns->v1.max_t[i]) % 1000); } } else if (ver->fcxnullsta == 7) { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); + p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[Tx:%d/", le32_to_cpu(ns->v7.result[i][4])); @@ -9896,13 +10551,13 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, "avg_t:%d.%03d/", le32_to_cpu(ns->v7.tavg[i]) / 1000, le32_to_cpu(ns->v7.tavg[i]) % 1000); - p += scnprintf(p, end - p, "max_t:%d.%03d]\n", + p += scnprintf(p, end - p, "max_t:%d.%03d]", le32_to_cpu(ns->v7.tmax[i]) / 1000, le32_to_cpu(ns->v7.tmax[i]) % 1000); } } else { for (i = 0; i < 2; i++) { - p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); + p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); p += scnprintf(p, end - p, "null-%d", i); p += scnprintf(p, end - p, "[Tx:%d/", le32_to_cpu(ns->v2.result[i][4])); @@ -9917,7 +10572,7 @@ static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) p += scnprintf(p, end - p, "avg_t:%d.%03d/", le32_to_cpu(ns->v2.avg_t[i]) / 1000, le32_to_cpu(ns->v2.avg_t[i]) % 1000); - p += scnprintf(p, end - p, "max_t:%d.%03d]\n", + p += scnprintf(p, end - p, "max_t:%d.%03d]", le32_to_cpu(ns->v2.max_t[i]) / 1000, le32_to_cpu(ns->v2.max_t[i]) % 1000); } @@ -10159,7 +10814,6 @@ static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", __func__); - p += scnprintf(p, end - p, "\n"); goto out; } @@ -10432,7 +11086,6 @@ static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) id_to_regtype(type), offset, val); cnt++; } - p += scnprintf(p, end - p, "\n"); out: return p - buf; @@ -11132,37 +11785,39 @@ static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) { - struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; const struct rtw89_btc_ver *ver = btc->ver; - struct rtw89_btc_cx *cx = &btc->cx; - struct rtw89_btc_bt_info *bt = &cx->bt; + struct rtw89_btc_dm *dm = &btc->dm; char *p = buf, *end = buf + bufsz; + dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; + + p += scnprintf(p, end - p, + "\n\n\n** Page:%3d/RunCNT:%3d **", + dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO], + dm->cnt_dm[BTC_DCNT_RUN]); p += scnprintf(p, end - p, - "=========================================\n"); + "\n========== [BTC FEATURE SUB VER] =========="); p += scnprintf(p, end - p, - "WL FW / BT FW %d.%d.%d.%d / NA\n", - fw_suit->major_ver, fw_suit->minor_ver, - fw_suit->sub_ver, fw_suit->sub_idex); - p += scnprintf(p, end - p, "manual %d\n", - btc->manual_ctrl); - + "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]", + "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt, + fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots, + ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta); p += scnprintf(p, end - p, - "=========================================\n"); - + "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]", + "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep, + fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg, + ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg); p += scnprintf(p, end - p, - "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", - "[bt_info]", - bt->raw_info[2], bt->raw_info[3], - bt->raw_info[4], bt->raw_info[5], - bt->raw_info[6], bt->raw_info[7], - bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", - cx->cnt_bt[BTC_BCNT_INFOUPDATE], - cx->cnt_bt[BTC_BCNT_INFOSAME]); - + "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]", + "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver, + fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh, + ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo); p += scnprintf(p, end - p, - "\n=========================================\n"); + "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],", + "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi, + fwsubver->fcxmlo, ver->fcxmlo); p += _show_cx_info(rtwdev, p, end - p); p += _show_wl_info(rtwdev, p, end - p); diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index e3a1fcd79620..ea2c1e5d70f5 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -224,6 +224,13 @@ enum btc_wl_mode { BTC_WL_MODE_NUM, }; +enum btc_mlo_rf_combin { + BTC_MLO_RF_2_PLUS_0 = 0, + BTC_MLO_RF_0_PLUS_2 = 1, + BTC_MLO_RF_1_PLUS_1 = 2, + BTC_MLO_RF_2_PLUS_2 = 3, +}; + enum btc_wl_gpio_debug { BTC_DBG_GNT_BT = 0, BTC_DBG_GNT_WL = 1, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 49447668cbf3..1f5639a5d166 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -204,6 +204,7 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = { }; static const u8 rtw89_ext_capa_sta[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, }; @@ -1722,7 +1723,7 @@ static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, }, [RTW89_CHIP_BE] = { 32, 40, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN, - VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, 16, 24, VAR_LEN, + VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, 88, 56, VAR_LEN, VAR_LEN, VAR_LEN, 0, 24, 24, 24, 24, 32, 32, 32, 32 }, }; @@ -1917,6 +1918,8 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev, return -EINVAL; pos = phy_ppdu->buf + PHY_STS_HDR_LEN; + if (phy_ppdu->hdr_2_en) + pos += PHY_STS_HDR_LEN; end = phy_ppdu->buf + phy_ppdu->len; while (pos < end) { const struct rtw89_phy_sts_iehdr *iehdr = pos; @@ -2158,6 +2161,11 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, if (rx_status->band != NL80211_BAND_6GHZ) return; + if (unlikely(!(rtwdev->chip->support_bands & BIT(NL80211_BAND_6GHZ)))) { + rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "invalid rx on unsupported 6 GHz\n"); + return; + } + ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, ies, skb->len); list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) { @@ -2477,6 +2485,41 @@ static void rtw89_core_update_rx_freq_from_ie(struct rtw89_dev *rtwdev, rx_status->freq = ieee80211_channel_to_frequency(chan, rx_status->band); } +static void rtw89_core_correct_mcc_chan(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status, + struct rtw89_rx_phy_ppdu *phy_ppdu) +{ + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + const struct rtw89_chan *chan; + u8 mac_id = desc_info->mac_id; + enum rtw89_entity_mode mode; + enum nl80211_band band; + + mode = rtw89_get_entity_mode(rtwdev); + if (likely(mode != RTW89_ENTITY_MODE_MCC)) + return; + + if (chip_gen == RTW89_CHIP_BE && phy_ppdu) + mac_id = phy_ppdu->mac_id; + + rcu_read_lock(); + + rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, mac_id); + if (!rtwsta_link) + goto out; + + rtwvif_link = rtwsta_link->rtwvif_link; + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + band = rtw89_hw_to_nl80211_band(chan->band_type); + rx_status->freq = ieee80211_channel_to_frequency(chan->primary_channel, band); + +out: + rcu_read_unlock(); +} + static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct rtw89_rx_desc_info *desc_info, @@ -2495,6 +2538,7 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status); rtw89_core_validate_rx_signal(rx_status); rtw89_core_update_rx_freq_from_ie(rtwdev, skb_ppdu, rx_status); + rtw89_core_correct_mcc_chan(rtwdev, desc_info, rx_status, phy_ppdu); /* In low power mode, it does RX in thread context. */ local_bh_disable(); @@ -2752,9 +2796,11 @@ static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev, } static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, + struct sk_buff *skb, struct rtw89_rx_desc_info *desc_info, struct ieee80211_rx_status *rx_status) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; const struct cfg80211_chan_def *chandef = rtw89_chandef_get(rtwdev, RTW89_CHANCTX_0); u16 data_rate; @@ -2766,6 +2812,10 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rx_status->freq = chandef->chan->center_freq; rx_status->band = chandef->chan->band; + if (ieee80211_is_beacon(hdr->frame_control) || + ieee80211_is_probe_resp(hdr->frame_control)) + rx_status->boottime_ns = ktime_get_boottime_ns(); + if (rtwdev->scanning && RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { const struct rtw89_chan *cur = rtw89_scan_chan_get(rtwdev); @@ -2922,7 +2972,7 @@ void rtw89_core_rx(struct rtw89_dev *rtwdev, rx_status = IEEE80211_SKB_RXCB(skb); memset(rx_status, 0, sizeof(*rx_status)); - rtw89_core_update_rx_status(rtwdev, desc_info, rx_status); + rtw89_core_update_rx_status(rtwdev, skb, desc_info, rx_status); rtw89_core_rx_pkt_hdl(rtwdev, skb, desc_info); if (desc_info->long_rxdesc && BIT(desc_info->frame_type) & PPDU_FILTER_BITMAP) @@ -3330,8 +3380,8 @@ static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, rtwvif_link); } -static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) +int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool qos, bool ps, int timeout) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1; @@ -3379,7 +3429,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, rcu_read_unlock(); return rtw89_core_tx_kick_off_and_wait(rtwdev, skb, qsel, - RTW89_ROC_TX_TIMEOUT); + timeout); out: rcu_read_unlock(); @@ -3416,7 +3466,8 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) pause_parm.trigger = rtwvif_link; rtw89_chanctx_pause(rtwdev, &pause_parm); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true, + RTW89_ROC_TX_TIMEOUT); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-1 failed: %d\n", ret); @@ -3476,7 +3527,8 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) roc->state = RTW89_ROC_IDLE; rtw89_config_roc_chandef(rtwdev, rtwvif_link, NULL); rtw89_chanctx_proceed(rtwdev, NULL); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false, + RTW89_ROC_TX_TIMEOUT); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-0 failed: %d\n", ret); @@ -3742,7 +3794,7 @@ static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work) lockdep_assert_wiphy(wiphy); - if (test_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags)) + if (test_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags)) return; if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) @@ -3967,6 +4019,12 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_CONN_START); rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + + if (vif->p2p) { + rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, + &rtwsta_link->tx_retry); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, 60); + } } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); if (ret) { @@ -4151,6 +4209,10 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, } rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + + if (vif->p2p) + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, + rtwsta_link->tx_retry); } rtw89_assoc_link_set(rtwsta_link); @@ -4169,6 +4231,10 @@ int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false); rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_DIS_CONN); + + if (vif->p2p) + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, + rtwsta_link->tx_retry); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_REMOVE); @@ -4655,6 +4721,43 @@ void rtw89_core_update_beacon_work(struct wiphy *wiphy, struct wiphy_work *work) rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); } +void rtw89_core_csa_beacon_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_vif_link *rtwvif_link = + container_of(work, struct rtw89_vif_link, csa_beacon_work.work); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct ieee80211_bss_conf *bss_conf; + unsigned int delay; + + lockdep_assert_wiphy(wiphy); + + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) + return; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (!bss_conf->csa_active) { + rcu_read_unlock(); + return; + } + + delay = ieee80211_tu_to_usec(bss_conf->beacon_int); + + rcu_read_unlock(); + + if (!ieee80211_beacon_cntdwn_is_complete(vif, rtwvif_link->link_id)) { + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); + + wiphy_delayed_work_queue(wiphy, &rtwvif_link->csa_beacon_work, + usecs_to_jiffies(delay)); + } else { + ieee80211_csa_finish(vif, rtwvif_link->link_id); + } +} + int rtw89_wait_for_cond(struct rtw89_wait_info *wait, unsigned int cond) { struct completion *cmpl = &wait->completion; @@ -4808,6 +4911,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_bt_devinfo_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_rfk_chk_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->cfo_track_work); + wiphy_delayed_work_cancel(wiphy, &rtwdev->mcc_prepare_done_work); cancel_delayed_work_sync(&rtwdev->forbid_ba_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->antdiv_work); @@ -5034,6 +5138,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) wiphy_delayed_work_init(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); wiphy_delayed_work_init(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); wiphy_delayed_work_init(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); + wiphy_delayed_work_init(&rtwdev->mcc_prepare_done_work, rtw89_mcc_prepare_done_work); INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); wiphy_delayed_work_init(&rtwdev->antdiv_work, rtw89_phy_antdiv_work); rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); @@ -5127,6 +5232,7 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, { struct ieee80211_bss_conf *bss_conf; struct rtw89_bb_ctx *bb; + int ret; if (!rtwvif_link) return; @@ -5146,6 +5252,14 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, rtw89_phy_config_edcca(rtwdev, bb, false); rtw89_tas_scan(rtwdev, false); + if (hw_scan) { + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, false, false, + RTW89_SCAN_NULL_TIMEOUT); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "scan send null-0 failed: %d\n", ret); + } + rtwdev->scanning = false; rtw89_for_each_active_bb(rtwdev, bb) bb->dig.bypass_dig = true; @@ -5239,7 +5353,8 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (unlikely(!ieee80211_vif_is_mld(vif))) return -EOPNOTSUPP; - if (unlikely(!(usable_links & BIT(link_id)))) { + if (unlikely(link_id >= IEEE80211_MLD_MAX_NUM_LINKS || + !(usable_links & BIT(link_id)))) { rtw89_warn(rtwdev, "%s: link id %u is not usable\n", __func__, link_id); return -ENOLINK; @@ -5504,6 +5619,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, CHANCTX_STA_CSA); if (chip->support_bandwidths & BIT(NL80211_CHAN_WIDTH_160)) ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); @@ -5530,6 +5646,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP | WIPHY_FLAG_AP_UAPSD | + WIPHY_FLAG_HAS_CHANNEL_SWITCH | WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK; if (!chip->support_rnr) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 1c8f3b9b7c4c..cdacf100a59a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1205,7 +1205,7 @@ struct rtw89_mac_ax_gnt { struct rtw89_mac_ax_wl_act { u8 wlan_act_en; u8 wlan_act; -}; +} __packed; #define RTW89_MAC_AX_COEX_GNT_NR 2 struct rtw89_mac_ax_coex_gnt { @@ -1322,6 +1322,7 @@ enum rtw89_btc_bt_state_cnt { BTC_BCNT_POLUT_NOW, BTC_BCNT_POLUT_DIFF, BTC_BCNT_RATECHG, + BTC_BCNT_BTTXPWR_UPDATE, BTC_BCNT_NUM, }; @@ -1557,6 +1558,25 @@ struct rtw89_btc_wl_dbcc_info { u8 role[RTW89_PHY_NUM]; /* role in each phy */ }; +struct rtw89_btc_wl_mlo_info { + u8 wmode[RTW89_PHY_NUM]; /* enum phl_mr_wmode */ + u8 ch_type[RTW89_PHY_NUM]; /* enum phl_mr_ch_type */ + u8 hwb_rf_band[RTW89_PHY_NUM]; /* enum band_type, RF-band for HW-band */ + u8 path_rf_band[RTW89_PHY_NUM]; /* enum band_type, RF-band for PHY0/1 */ + + u8 wtype; /* enum phl_mr_wtype */ + u8 mrcx_mode; + u8 mrcx_act_hwb_map; + u8 mrcx_bt_slot_rsp; + + u8 rf_combination; /* enum btc_mlo_rf_combin 0:2+0, 1:0+2, 2:1+1,3:2+2 */ + u8 mlo_en; /* MLO enable */ + u8 mlo_adie; /* a-die count */ + u8 dual_hw_band_en; /* both 2 HW-band link exist */ + + u32 link_status; /* enum mlo_dbcc_mode_type */ +}; + struct rtw89_btc_wl_active_role { u8 connected: 1; u8 pid: 3; @@ -1791,6 +1811,13 @@ union rtw89_btc_bt_state_map { #define BTC_BT_AFH_GROUP 12 #define BTC_BT_AFH_LE_GROUP 5 +struct rtw89_btc_bt_txpwr_desc { + s8 br_dbm; + s8 le_dbm; + u8 br_gain_index; + u8 le_gain_index; +}; + struct rtw89_btc_bt_link_info { struct rtw89_btc_u8_sta_chg profile_cnt; struct rtw89_btc_bool_sta_chg multi_link; @@ -1800,6 +1827,7 @@ struct rtw89_btc_bt_link_info { struct rtw89_btc_bt_a2dp_desc a2dp_desc; struct rtw89_btc_bt_pan_desc pan_desc; union rtw89_btc_bt_state_map status; + struct rtw89_btc_bt_txpwr_desc bt_txpwr_desc; u8 sut_pwr_level[BTC_PROFILE_MAX]; u8 golden_rx_shift[BTC_PROFILE_MAX]; @@ -1895,6 +1923,7 @@ struct rtw89_btc_wl_info { struct rtw89_btc_wl_role_info_v8 role_info_v8; struct rtw89_btc_wl_scan_info scan_info; struct rtw89_btc_wl_dbcc_info dbcc_info; + struct rtw89_btc_wl_mlo_info mlo_info; struct rtw89_btc_rf_para rf_para; struct rtw89_btc_wl_nhm nhm; union rtw89_btc_wl_state_map status; @@ -1907,12 +1936,16 @@ struct rtw89_btc_wl_info { u8 bt_polut_type[RTW89_PHY_NUM]; /* BT polluted WL-Tx type for phy0/1 */ bool is_5g_hi_channel; + bool go_client_exist; + bool noa_exist; bool pta_reg_mac_chg; bool bg_mode; bool he_mode; bool scbd_change; bool fw_ver_mismatch; bool client_cnt_inc_2g; + bool link_mode_chg; + bool dbcc_chg; u32 scbd; }; @@ -2065,6 +2098,7 @@ struct rtw89_btc_bt_info { union rtw89_btc_bt_rfk_info_map rfk_info; u8 raw_info[BTC_BTINFO_MAX]; /* raw bt info from mailbox */ + u8 txpwr_info[BTC_BTINFO_MAX]; u8 rssi_level; u32 scbd; @@ -2903,12 +2937,32 @@ struct rtw89_btc_trx_info { u32 rx_err_ratio; }; +enum btc_rf_path { + BTC_RF_S0 = 0, + BTC_RF_S1 = 1, + BTC_RF_NUM, +}; + +struct rtw89_btc_fbtc_outsrc_set_info { + u8 rf_band[BTC_RF_NUM]; /* 0:2G, 1:non-2G */ + u8 btg_rx[BTC_RF_NUM]; + u8 nbtg_tx[BTC_RF_NUM]; + + struct rtw89_mac_ax_gnt gnt_set[BTC_RF_NUM]; /* refer to btc_gnt_ctrl */ + struct rtw89_mac_ax_wl_act wlact_set[BTC_RF_NUM]; /* BT0/BT1 */ + + u8 pta_req_hw_band; + u8 rf_gbt_source; +} __packed; + union rtw89_btc_fbtc_slot_u { struct rtw89_btc_fbtc_slot v1[CXST_MAX]; struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX]; }; struct rtw89_btc_dm { + struct rtw89_btc_fbtc_outsrc_set_info ost_info_last; /* outsrc API setup info */ + struct rtw89_btc_fbtc_outsrc_set_info ost_info; /* outsrc API setup info */ union rtw89_btc_fbtc_slot_u slot; union rtw89_btc_fbtc_slot_u slot_now; struct rtw89_btc_fbtc_tdma tdma; @@ -2998,6 +3052,7 @@ enum rtw89_btc_btf_fw_event { BTF_EVNT_BT_LEAUDIO_INFO = 7, /* fwc2hfunc > 1 */ BTF_EVNT_BUF_OVERFLOW, BTF_EVNT_C2H_LOOPBACK, + BTF_EVNT_BT_QUERY_TXPWR, /* fwc2hfunc > 3 */ BTF_EVNT_MAX, }; @@ -3116,31 +3171,6 @@ enum rtw89_btc_btfre_type { BTFRE_MAX, }; -struct rtw89_btc_btf_fwinfo { - u32 cnt_c2h; - u32 cnt_h2c; - u32 cnt_h2c_fail; - u32 event[BTF_EVNT_MAX]; - - u32 err[BTFRE_MAX]; - u32 len_mismch; - u32 fver_mismch; - u32 rpt_en_map; - - struct rtw89_btc_report_ctrl_state rpt_ctrl; - struct rtw89_btc_rpt_fbtc_tdma rpt_fbtc_tdma; - struct rtw89_btc_rpt_fbtc_slots rpt_fbtc_slots; - struct rtw89_btc_rpt_fbtc_cysta rpt_fbtc_cysta; - struct rtw89_btc_rpt_fbtc_step rpt_fbtc_step; - struct rtw89_btc_rpt_fbtc_nullsta rpt_fbtc_nullsta; - struct rtw89_btc_rpt_fbtc_mreg rpt_fbtc_mregval; - struct rtw89_btc_rpt_fbtc_gpio_dbg rpt_fbtc_gpio_dbg; - struct rtw89_btc_rpt_fbtc_btver rpt_fbtc_btver; - struct rtw89_btc_rpt_fbtc_btscan rpt_fbtc_btscan; - struct rtw89_btc_rpt_fbtc_btafh rpt_fbtc_btafh; - struct rtw89_btc_rpt_fbtc_btdev rpt_fbtc_btdev; -}; - struct rtw89_btc_ver { enum rtw89_core_chip_id chip_id; u32 fw_ver_code; @@ -3167,6 +3197,35 @@ struct rtw89_btc_ver { u8 drvinfo_type; u16 info_buf; u8 max_role_num; + u8 fcxosi; + u8 fcxmlo; + u8 bt_desired; +}; + +struct rtw89_btc_btf_fwinfo { + u32 cnt_c2h; + u32 cnt_h2c; + u32 cnt_h2c_fail; + u32 event[BTF_EVNT_MAX]; + + u32 err[BTFRE_MAX]; + u32 len_mismch; + u32 fver_mismch; + u32 rpt_en_map; + + struct rtw89_btc_ver fw_subver; + struct rtw89_btc_report_ctrl_state rpt_ctrl; + struct rtw89_btc_rpt_fbtc_tdma rpt_fbtc_tdma; + struct rtw89_btc_rpt_fbtc_slots rpt_fbtc_slots; + struct rtw89_btc_rpt_fbtc_cysta rpt_fbtc_cysta; + struct rtw89_btc_rpt_fbtc_step rpt_fbtc_step; + struct rtw89_btc_rpt_fbtc_nullsta rpt_fbtc_nullsta; + struct rtw89_btc_rpt_fbtc_mreg rpt_fbtc_mregval; + struct rtw89_btc_rpt_fbtc_gpio_dbg rpt_fbtc_gpio_dbg; + struct rtw89_btc_rpt_fbtc_btver rpt_fbtc_btver; + struct rtw89_btc_rpt_fbtc_btscan rpt_fbtc_btscan; + struct rtw89_btc_rpt_fbtc_btafh rpt_fbtc_btafh; + struct rtw89_btc_rpt_fbtc_btdev rpt_fbtc_btdev; }; #define RTW89_BTC_POLICY_MAXLEN 512 @@ -3385,6 +3444,7 @@ struct rtw89_sta_link { unsigned int link_id; u8 mac_id; + u8 tx_retry; bool er_cap; struct rtw89_vif_link *rtwvif_link; struct rtw89_ra_info ra; @@ -3440,6 +3500,8 @@ struct rtw89_tx_skb_data { u8 hci_priv[]; }; +#define RTW89_SCAN_NULL_TIMEOUT 30 + #define RTW89_ROC_IDLE_TIMEOUT 500 #define RTW89_ROC_TX_TIMEOUT 30 enum rtw89_roc_state { @@ -3533,6 +3595,7 @@ struct rtw89_vif_link { bool pwr_diff_en; u8 def_tri_idx; struct wiphy_work update_beacon_work; + struct wiphy_delayed_work csa_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]; @@ -3645,6 +3708,8 @@ struct rtw89_chip_ops { enum rtw89_phy_idx phy_idx); int (*init_txpwr_unit)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); u8 (*get_thermal)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path); + u32 (*chan_to_rf18_val)(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan); void (*ctrl_btg_bt_rx)(struct rtw89_dev *rtwdev, bool en, enum rtw89_phy_idx phy_idx); void (*query_ppdu)(struct rtw89_dev *rtwdev, @@ -4358,7 +4423,6 @@ struct rtw89_chip_info { u32 para_ver; u32 wlcx_desired; - u8 btcx_desired; u8 scbd; u8 mailbox; @@ -4513,6 +4577,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, RTW89_FW_FEATURE_RFK_RXDCK_V0, + RTW89_FW_FEATURE_RFK_IQK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, RTW89_FW_FEATURE_NOTIFY_AP_INFO, RTW89_FW_FEATURE_CH_INFO_BE_V0, @@ -4520,6 +4585,8 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_NO_PHYCAP_P1, RTW89_FW_FEATURE_NO_POWER_DIFFERENCE, RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1, + RTW89_FW_FEATURE_SCAN_OFFLOAD_EXTRA_OP, + RTW89_FW_FEATURE_RFK_NTFY_MCC_V0, }; struct rtw89_fw_suit { @@ -4912,7 +4979,7 @@ enum rtw89_flags { RTW89_FLAG_CRASH_SIMULATING, RTW89_FLAG_SER_HANDLING, RTW89_FLAG_WOWLAN, - RTW89_FLAG_FORBIDDEN_TRACK_WROK, + RTW89_FLAG_FORBIDDEN_TRACK_WORK, RTW89_FLAG_CHANGING_INTERFACE, RTW89_FLAG_HW_RFKILL_STATE, @@ -5447,11 +5514,18 @@ struct rtw89_early_h2c { u16 h2c_len; }; +struct rtw89_hw_scan_extra_op { + bool set; + u8 macid; + struct rtw89_chan chan; +}; + struct rtw89_hw_scan_info { struct rtw89_vif_link *scanning_vif; struct list_head pkt_list[NUM_NL80211_BANDS]; struct list_head chan_list; struct rtw89_chan op_chan; + struct rtw89_hw_scan_extra_op extra_op; bool connected; bool abort; }; @@ -5672,6 +5746,7 @@ struct rtw89_mcc_role { /* byte-array in LE order for FW */ u8 macid_bitmap[BITS_TO_BYTES(RTW89_MAX_MAC_ID_NUM)]; + u8 probe_count; u16 duration; /* TU */ u16 beacon_interval; /* TU */ @@ -5728,6 +5803,7 @@ struct rtw89_mcc_config { struct rtw89_mcc_sync sync; u64 start_tsf; u64 start_tsf_in_aux_domain; + u64 prepare_delay; u16 mcc_interval; /* TU */ u16 beacon_offset; /* TU */ }; @@ -5858,6 +5934,7 @@ struct rtw89_dev { struct wiphy_delayed_work coex_bt_devinfo_work; struct wiphy_delayed_work coex_rfk_chk_work; struct wiphy_delayed_work cfo_track_work; + struct wiphy_delayed_work mcc_prepare_done_work; struct delayed_work forbid_ba_work; struct wiphy_delayed_work antdiv_work; struct rtw89_ppdu_sts_info ppdu_sts; @@ -6880,6 +6957,17 @@ static inline u8 rtw89_chip_get_thermal(struct rtw89_dev *rtwdev, return chip->ops->get_thermal(rtwdev, rf_path); } +static inline u32 rtw89_chip_chan_to_rf18_val(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!chip->ops->chan_to_rf18_val) + return 0; + + return chip->ops->chan_to_rf18_val(rtwdev, chan); +} + static inline void rtw89_chip_query_ppdu(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct ieee80211_rx_status *status) @@ -7317,6 +7405,9 @@ void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond, int rtw89_core_start(struct rtw89_dev *rtwdev); void rtw89_core_stop(struct rtw89_dev *rtwdev); void rtw89_core_update_beacon_work(struct wiphy *wiphy, struct wiphy_work *work); +void rtw89_core_csa_beacon_work(struct wiphy *wiphy, struct wiphy_work *work); +int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool qos, bool ps, int timeout); void rtw89_roc_work(struct wiphy *wiphy, struct wiphy_work *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); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index d6016fa107fb..4acb567b3ad4 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -1114,6 +1114,7 @@ static int rtw89_debug_dump_mac_mem(struct rtw89_dev *rtwdev, const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u32 filter_model_addr = mac->filter_model_addr; u32 indir_access_addr = mac->indir_access_addr; + u32 mem_page_size = mac->mem_page_size; u32 base_addr, start_page, residue; char *p = buf, *end = buf + bufsz; u32 i, j, pp, pages; @@ -1121,14 +1122,14 @@ static int rtw89_debug_dump_mac_mem(struct rtw89_dev *rtwdev, u32 val; remain = len; - pages = len / MAC_MEM_DUMP_PAGE_SIZE + 1; - start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE; - residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE; + pages = len / mem_page_size + 1; + start_page = start_addr / mem_page_size; + residue = start_addr % mem_page_size; base_addr = mac->mem_base_addrs[sel]; - base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE; + base_addr += start_page * mem_page_size; for (pp = 0; pp < pages; pp++) { - dump_len = min_t(u32, remain, MAC_MEM_DUMP_PAGE_SIZE); + dump_len = min_t(u32, remain, mem_page_size); rtw89_write32(rtwdev, filter_model_addr, base_addr); for (i = indir_access_addr + residue; i < indir_access_addr + dump_len;) { @@ -1142,7 +1143,7 @@ static int rtw89_debug_dump_mac_mem(struct rtw89_dev *rtwdev, } p += scnprintf(p, end - p, "\n"); } - base_addr += MAC_MEM_DUMP_PAGE_SIZE; + base_addr += mem_page_size; } return p - buf; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 00b65b2995cf..c613431e754f 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -833,17 +833,20 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 91, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 110, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS), + __CFG_FW_FEAT(RTL8852C, ge, 0, 0, 0, 0, RFK_NTFY_MCC_V0), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 80, 0, WOW_REASON_V1), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, BEACON_LOSS_COUNT_V1), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0), __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, 28, 0, RFK_IQK_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), @@ -3030,12 +3033,10 @@ fail: #define H2C_P2P_ACT_LEN 20 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) + u8 act, u8 noa_id, u8 ctwindow_oppps) { 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; @@ -5083,6 +5084,46 @@ fail: return ret; } +int rtw89_fw_h2c_cxdrv_osi_info(struct rtw89_dev *rtwdev, u8 type) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_fbtc_outsrc_set_info *osi = &btc->dm.ost_info; + struct rtw89_h2c_cxosi *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_osi\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cxosi *)skb->data; + + h2c->hdr.type = type; + h2c->hdr.ver = btc->ver->fcxosi; + h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7; + h2c->osi = *osi; + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, BTFC_SET, + SET_DRV_INFO, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + #define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR) int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type) { @@ -5361,6 +5402,7 @@ static int rtw89_fw_h2c_scan_list_offload_ax(struct rtw89_dev *rtwdev, int ch_num, struct list_head *chan_list) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_h2c_chinfo_elem *elem; struct rtw89_mac_chinfo_ax *ch_info; @@ -5403,6 +5445,10 @@ int rtw89_fw_h2c_scan_list_offload_ax(struct rtw89_dev *rtwdev, int ch_num, le32_encode_bits(ch_info->tx_null, RTW89_H2C_CHINFO_W1_TX_NULL) | le32_encode_bits(ch_info->rand_seq_num, RTW89_H2C_CHINFO_W1_RANDOM); + if (scan_info->extra_op.set) + elem->w1 |= le32_encode_bits(ch_info->macid_tx, + RTW89_H2C_CHINFO_W1_MACID_TX); + elem->w2 = le32_encode_bits(ch_info->pkt_id[0], RTW89_H2C_CHINFO_W2_PKT0) | le32_encode_bits(ch_info->pkt_id[1], RTW89_H2C_CHINFO_W2_PKT1) | le32_encode_bits(ch_info->pkt_id[2], RTW89_H2C_CHINFO_W2_PKT2) | @@ -5543,6 +5589,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool wowlan) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; enum rtw89_scan_mode scan_mode = RTW89_SCAN_IMMEDIATE; @@ -5602,6 +5649,10 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, h2c->tsf_low = le32_encode_bits(lower_32_bits(tsf), RTW89_H2C_SCANOFLD_W4_TSF_LOW); + if (scan_info->extra_op.set) + h2c->w6 = le32_encode_bits(scan_info->extra_op.macid, + RTW89_H2C_SCANOFLD_W6_SECOND_MACID); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, H2C_FUNC_SCANOFLD, 1, 1, @@ -5877,31 +5928,48 @@ fail: int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev) { struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_fw_h2c_rf_get_mccch_v0 *mccch_v0; struct rtw89_fw_h2c_rf_get_mccch *mccch; + u32 len = sizeof(*mccch); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; u8 idx; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, sizeof(*mccch)); + if (RTW89_CHK_FW_FEATURE(RFK_NTFY_MCC_V0, &rtwdev->fw)) { + len = sizeof(*mccch_v0); + ver = 0; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n"); return -ENOMEM; } - skb_put(skb, sizeof(*mccch)); - mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data; + skb_put(skb, len); idx = rfk_mcc->table_idx; - mccch->ch_0 = cpu_to_le32(rfk_mcc->ch[0]); - mccch->ch_1 = cpu_to_le32(rfk_mcc->ch[1]); - mccch->band_0 = cpu_to_le32(rfk_mcc->band[0]); - mccch->band_1 = cpu_to_le32(rfk_mcc->band[1]); - mccch->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); - mccch->current_band_type = cpu_to_le32(rfk_mcc->band[idx]); + if (ver == 0) { + mccch_v0 = (struct rtw89_fw_h2c_rf_get_mccch_v0 *)skb->data; + mccch_v0->ch_0 = cpu_to_le32(rfk_mcc->ch[0]); + mccch_v0->ch_1 = cpu_to_le32(rfk_mcc->ch[1]); + mccch_v0->band_0 = cpu_to_le32(rfk_mcc->band[0]); + mccch_v0->band_1 = cpu_to_le32(rfk_mcc->band[1]); + mccch_v0->current_band_type = cpu_to_le32(rfk_mcc->band[idx]); + mccch_v0->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); + } else { + mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data; + mccch->ch_0_0 = cpu_to_le32(rfk_mcc->ch[0]); + mccch->ch_0_1 = cpu_to_le32(rfk_mcc->ch[0]); + mccch->ch_1_0 = cpu_to_le32(rfk_mcc->ch[1]); + mccch->ch_1_1 = cpu_to_le32(rfk_mcc->ch[1]); + mccch->current_channel = cpu_to_le32(rfk_mcc->ch[idx]); + } rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, H2C_FUNC_OUTSRC_RF_GET_MCCCH, 0, 0, - sizeof(*mccch)); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -5917,6 +5985,65 @@ fail: } EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc); +int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_h2c_rf_ps_info *h2c; + const struct rtw89_chan *chan; + u32 len = sizeof(*h2c); + unsigned int link_id; + struct sk_buff *skb; + int ret; + u8 path; + u32 val; + + if (chip->chip_gen != RTW89_CHIP_BE) + return 0; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c rf ps info\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_rf_ps_info *)skb->data; + h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + path = rtw89_phy_get_syn_sel(rtwdev, rtwvif_link->phy_idx); + val = rtw89_chip_chan_to_rf18_val(rtwdev, chan); + + if (path >= chip->rf_path_num) { + rtw89_err(rtwdev, "unsupported rf path (%d)\n", path); + ret = -ENOENT; + goto fail; + } + + h2c->rf18[path] = cpu_to_le32(val); + h2c->pri_ch[path] = chan->primary_channel; + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, + H2C_FUNC_OUTSRC_RF_PS_INFO, 0, 0, + sizeof(*h2c)); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_rf_ps_info); + int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -6031,6 +6158,7 @@ fail: int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode) { + struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_h2c_rf_tssi *h2c; u32 len = sizeof(*h2c); @@ -6053,6 +6181,7 @@ int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, h2c->hwtx_en = true; h2c->cv = hal->cv; h2c->tssi_mode = tssi_mode; + h2c->rfe_type = efuse->rfe_type; rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(rtwdev, phy_idx, chan, h2c); rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(rtwdev, phy_idx, chan, h2c); @@ -6077,22 +6206,47 @@ fail: int rtw89_fw_h2c_rf_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan) { + struct rtw89_hal *hal = &rtwdev->hal; + struct rtw89_h2c_rf_iqk_v0 *h2c_v0; struct rtw89_h2c_rf_iqk *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; + if (RTW89_CHK_FW_FEATURE(RFK_IQK_V0, &rtwdev->fw)) { + len = sizeof(*h2c_v0); + ver = 0; + } + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c RF IQK\n"); return -ENOMEM; } skb_put(skb, len); + + if (ver == 0) { + h2c_v0 = (struct rtw89_h2c_rf_iqk_v0 *)skb->data; + + h2c_v0->phy_idx = cpu_to_le32(phy_idx); + h2c_v0->dbcc = cpu_to_le32(rtwdev->dbcc_en); + + goto done; + } + h2c = (struct rtw89_h2c_rf_iqk *)skb->data; - h2c->phy_idx = cpu_to_le32(phy_idx); - h2c->dbcc = cpu_to_le32(rtwdev->dbcc_en); + h2c->len = sizeof(*h2c); + h2c->ktype = 0; + h2c->phy = phy_idx; + h2c->kpath = rtw89_phy_get_kpath(rtwdev, phy_idx); + h2c->band = chan->band_type; + h2c->bw = chan->band_width; + h2c->ch = chan->channel; + h2c->cv = hal->cv; +done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, H2C_FUNC_RFK_IQK_OFFLOAD, 0, 0, len); @@ -6845,6 +6999,7 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_request *req = rtwvif->scan_req; @@ -6915,6 +7070,15 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, case RTW89_CHAN_ACTIVE: ch_info->pause_data = true; break; + case RTW89_CHAN_EXTRA_OP: + ch_info->central_ch = ext->chan.channel; + ch_info->pri_ch = ext->chan.primary_channel; + ch_info->ch_band = ext->chan.band_type; + ch_info->bw = ext->chan.band_width; + ch_info->tx_null = true; + ch_info->num_pkt = 0; + ch_info->macid_tx = true; + break; default: rtw89_err(rtwdev, "Channel type out of bound\n"); } @@ -7073,10 +7237,45 @@ out: return ret; } +static int rtw89_hw_scan_add_op_types_ax(struct rtw89_dev *rtwdev, + enum rtw89_chan_type type, + struct list_head *chan_list, + struct cfg80211_scan_request *req, + int *off_chan_time) +{ + struct rtw89_mac_chinfo_ax *tmp; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + switch (type) { + case RTW89_CHAN_OPERATE: + tmp->period = req->duration_mandatory ? + req->duration : RTW89_CHANNEL_TIME; + *off_chan_time = 0; + break; + case RTW89_CHAN_EXTRA_OP: + tmp->period = RTW89_CHANNEL_TIME_EXTRA_OP; + /* still calc @off_chan_time for scan op */ + *off_chan_time += tmp->period; + break; + default: + kfree(tmp); + return -EINVAL; + } + + rtw89_hw_scan_add_chan_ax(rtwdev, type, 0, tmp); + list_add_tail(&tmp->list, chan_list); + + return 0; +} + int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo_ax *ch_info, *tmp; @@ -7103,6 +7302,8 @@ int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev, else if (channel->band == NL80211_BAND_6GHZ) ch_info->period = RTW89_CHANNEL_TIME_6G + RTW89_DWELL_TIME_6G; + else if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + ch_info->period = RTW89_P2P_CHAN_TIME; else ch_info->period = RTW89_CHANNEL_TIME; @@ -7119,22 +7320,28 @@ int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev, type = RTW89_CHAN_ACTIVE; rtw89_hw_scan_add_chan_ax(rtwdev, type, req->n_ssids, ch_info); - if (scan_info->connected && - off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME) { - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) { - ret = -ENOMEM; - kfree(ch_info); - goto out; - } + if (!(scan_info->connected && + off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME)) + goto next; + + ret = rtw89_hw_scan_add_op_types_ax(rtwdev, RTW89_CHAN_OPERATE, + &chan_list, req, &off_chan_time); + if (ret) { + kfree(ch_info); + goto out; + } - type = RTW89_CHAN_OPERATE; - tmp->period = req->duration_mandatory ? - req->duration : RTW89_CHANNEL_TIME; - rtw89_hw_scan_add_chan_ax(rtwdev, type, 0, tmp); - list_add_tail(&tmp->list, &chan_list); - off_chan_time = 0; + if (!ext->set) + goto next; + + ret = rtw89_hw_scan_add_op_types_ax(rtwdev, RTW89_CHAN_EXTRA_OP, + &chan_list, req, &off_chan_time); + if (ret) { + kfree(ch_info); + goto out; } + +next: list_add_tail(&ch_info->list, &chan_list); off_chan_time += ch_info->period; } @@ -7273,6 +7480,8 @@ int rtw89_hw_scan_prep_chan_list_be(struct rtw89_dev *rtwdev, ch_info->period = req->duration; else if (channel->band == NL80211_BAND_6GHZ) ch_info->period = RTW89_CHANNEL_TIME_6G + RTW89_DWELL_TIME_6G; + else if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + ch_info->period = RTW89_P2P_CHAN_TIME; else ch_info->period = RTW89_CHANNEL_TIME; @@ -7436,6 +7645,47 @@ static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, } } +static void rtw89_hw_scan_set_extra_op_info(struct rtw89_dev *rtwdev, + struct rtw89_vif *scan_rtwvif, + const struct rtw89_chan *scan_op) +{ + struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; + struct rtw89_vif *tmp; + + ext->set = false; + if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD_EXTRA_OP, &rtwdev->fw)) + return; + + list_for_each_entry(tmp, &mgnt->active_list, mgnt_entry) { + const struct rtw89_chan *tmp_chan; + struct rtw89_vif_link *tmp_link; + + if (tmp == scan_rtwvif) + continue; + + tmp_link = rtw89_vif_get_link_inst(tmp, 0); + if (unlikely(!tmp_link)) { + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: no HW-0 link for extra op\n"); + continue; + } + + tmp_chan = rtw89_chan_get(rtwdev, tmp_link->chanctx_idx); + *ext = (struct rtw89_hw_scan_extra_op){ + .set = true, + .macid = tmp_link->mac_id, + .chan = *tmp_chan, + }; + + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: extra op: center %d primary %d\n", + ext->chan.channel, ext->chan.primary_channel); + break; + } +} + int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) @@ -7458,6 +7708,12 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, /* clone op and keep it during scan */ rtwdev->scan_info.op_chan = *chan; + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "hw scan: op: center %d primary %d\n", + chan->channel, chan->primary_channel); + + rtw89_hw_scan_set_extra_op_info(rtwdev, rtwvif, chan); + rtwdev->scan_info.connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); rtwdev->scan_info.scanning_vif = rtwvif_link; rtwdev->scan_info.abort = false; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 0fcc824e41be..24d2e8b0d079 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -237,6 +237,7 @@ enum rtw89_chan_type { RTW89_CHAN_OPERATE = 0, RTW89_CHAN_ACTIVE, RTW89_CHAN_DFS, + RTW89_CHAN_EXTRA_OP, }; enum rtw89_p2pps_action { @@ -316,8 +317,10 @@ struct rtw89_fw_macid_pause_sleep_grp { #define RTW89_H2C_MAX_SIZE 2048 #define RTW89_CHANNEL_TIME 45 #define RTW89_CHANNEL_TIME_6G 20 +#define RTW89_CHANNEL_TIME_EXTRA_OP 30 #define RTW89_DFS_CHAN_TIME 105 #define RTW89_OFF_CHAN_TIME 100 +#define RTW89_P2P_CHAN_TIME 105 #define RTW89_DWELL_TIME 20 #define RTW89_DWELL_TIME_6G 10 #define RTW89_SCAN_WIDTH 0 @@ -352,7 +355,8 @@ struct rtw89_mac_chinfo_ax { u8 tx_null:1; u8 rand_seq_num:1; u8 cfg_tx_pwr:1; - u8 rsvd0: 4; + u8 macid_tx: 1; + u8 rsvd0: 3; u8 pkt_id[RTW89_SCANOFLD_MAX_SSID]; u16 tx_pwr_idx; u8 rsvd1; @@ -2247,6 +2251,11 @@ struct rtw89_h2c_cxrole_v8 { struct rtw89_btc_wl_role_info_v8_u32 _u32; } __packed; +struct rtw89_h2c_cxosi { + struct rtw89_h2c_cxhdr_v7 hdr; + struct rtw89_btc_fbtc_outsrc_set_info osi; +} __packed; + struct rtw89_h2c_cxinit { struct rtw89_h2c_cxhdr hdr; u8 ant_type; @@ -2674,6 +2683,7 @@ struct rtw89_h2c_chinfo_elem { #define RTW89_H2C_CHINFO_W1_TX_NULL BIT(25) #define RTW89_H2C_CHINFO_W1_RANDOM BIT(26) #define RTW89_H2C_CHINFO_W1_CFG_TX BIT(27) +#define RTW89_H2C_CHINFO_W1_MACID_TX BIT(29) #define RTW89_H2C_CHINFO_W2_PKT0 GENMASK(7, 0) #define RTW89_H2C_CHINFO_W2_PKT1 GENMASK(15, 8) #define RTW89_H2C_CHINFO_W2_PKT2 GENMASK(23, 16) @@ -2773,6 +2783,7 @@ struct rtw89_h2c_scanofld { #define RTW89_H2C_SCANOFLD_W2_SLOW_PD GENMASK(23, 16) #define RTW89_H2C_SCANOFLD_W3_TSF_HIGH GENMASK(31, 0) #define RTW89_H2C_SCANOFLD_W4_TSF_LOW GENMASK(31, 0) +#define RTW89_H2C_SCANOFLD_W6_SECOND_MACID GENMASK(31, 24) struct rtw89_h2c_scanofld_be_macc_role { __le32 w0; @@ -4337,6 +4348,7 @@ enum rtw89_mrc_h2c_func { #define H2C_CL_OUTSRC_RF_REG_B 0x9 #define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa #define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2 +#define H2C_FUNC_OUTSRC_RF_PS_INFO 0x10 #define H2C_CL_OUTSRC_RF_FW_RFK 0xb enum rtw89_rfk_offload_h2c_func { @@ -4350,6 +4362,14 @@ enum rtw89_rfk_offload_h2c_func { }; struct rtw89_fw_h2c_rf_get_mccch { + __le32 ch_0_0; + __le32 ch_0_1; + __le32 ch_1_0; + __le32 ch_1_1; + __le32 current_channel; +} __packed; + +struct rtw89_fw_h2c_rf_get_mccch_v0 { __le32 ch_0; __le32 ch_1; __le32 band_0; @@ -4361,6 +4381,12 @@ struct rtw89_fw_h2c_rf_get_mccch { #define NUM_OF_RTW89_FW_RFK_PATH 2 #define NUM_OF_RTW89_FW_RFK_TBL 3 +struct rtw89_h2c_rf_ps_info { + __le32 rf18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; + u8 pri_ch[NUM_OF_RTW89_FW_RFK_PATH]; +} __packed; + struct rtw89_fw_h2c_rfk_pre_info_common { struct { __le32 ch[NUM_OF_RTW89_FW_RFK_PATH][NUM_OF_RTW89_FW_RFK_TBL]; @@ -4435,13 +4461,25 @@ struct rtw89_h2c_rf_tssi { u8 pg_thermal[2]; u8 ftable[2][128]; u8 tssi_mode; + u8 rfe_type; } __packed; -struct rtw89_h2c_rf_iqk { +struct rtw89_h2c_rf_iqk_v0 { __le32 phy_idx; __le32 dbcc; } __packed; +struct rtw89_h2c_rf_iqk { + u8 len; + u8 ktype; + u8 phy; + u8 kpath; + u8 band; + u8 bw; + u8 ch; + u8 cv; +} __packed; + struct rtw89_h2c_rf_dpk { u8 len; u8 phy; @@ -4713,6 +4751,7 @@ int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v7(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type); +int rtw89_fw_h2c_cxdrv_osi_info(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_ctrl_v7(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_trx(struct rtw89_dev *rtwdev, u8 type); @@ -4732,6 +4771,7 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, struct rtw89_fw_h2c_rf_reg_info *info, u16 len, u8 page); int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev); +int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, @@ -4815,9 +4855,8 @@ 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 rtw89_vif_link *rtwvif_link, - struct ieee80211_bss_conf *bss_conf, struct ieee80211_p2p_noa_desc *desc, - u8 act, u8 noa_id); + u8 act, u8 noa_id, u8 ctwindow_oppps); int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool en); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 9f0e30e75009..53628838a7c5 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4388,7 +4388,33 @@ static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } -void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) +static void rtw89_mac_enable_ap_bcn_by_chan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + const struct rtw89_chan *to_match, + bool en) +{ + const struct rtw89_chan *chan; + + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) + return; + + if (!to_match) + goto doit; + + /* @to_match may not be in the same domain as return of calling + * rtw89_chan_get(). So, cannot compare their addresses directly. + */ + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->channel != to_match->channel) + return; + +doit: + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); +} + +static void rtw89_mac_enable_aps_bcn_by_chan(struct rtw89_dev *rtwdev, + const struct rtw89_chan *to_match, + bool en) { struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; @@ -4396,8 +4422,13 @@ void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) rtw89_for_each_rtwvif(rtwdev, rtwvif) 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); + rtw89_mac_enable_ap_bcn_by_chan(rtwdev, rtwvif_link, + to_match, en); +} + +void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) +{ + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, NULL, en); } static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, @@ -4891,11 +4922,22 @@ rtw89_mac_c2h_macid_pause(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len { } -static bool rtw89_is_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel) +static const struct rtw89_chan * +rtw89_hw_scan_search_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel) { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; const struct rtw89_chan *op = &rtwdev->scan_info.op_chan; - return band == op->band_type && channel == op->primary_channel; + if (band == op->band_type && channel == op->primary_channel) + return op; + + if (scan_info->extra_op.set) { + op = &scan_info->extra_op.chan; + if (band == op->band_type && channel == op->primary_channel) + return op; + } + + return NULL; } static void @@ -4905,6 +4947,7 @@ 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 rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + const struct rtw89_chan *op_chan; struct rtw89_vif *rtwvif; struct rtw89_chan new; u16 actual_period, expect_period; @@ -4960,8 +5003,9 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, switch (reason) { case RTW89_SCAN_LEAVE_OP_NOTIFY: case RTW89_SCAN_LEAVE_CH_NOTIFY: - if (rtw89_is_op_chan(rtwdev, band, chan)) { - rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, false); + op_chan = rtw89_hw_scan_search_op_chan(rtwdev, band, chan); + if (op_chan) { + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, op_chan, false); ieee80211_stop_queues(rtwdev->hw); } return; @@ -4982,10 +5026,10 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, 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_link->chanctx_idx, - &rtwdev->scan_info.op_chan); - rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + op_chan = rtw89_hw_scan_search_op_chan(rtwdev, band, chan); + if (op_chan) { + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, op_chan); + rtw89_mac_enable_aps_bcn_by_chan(rtwdev, op_chan, true); ieee80211_wake_queues(rtwdev->hw); } else { rtw89_chan_create(&new, chan, chan, band, @@ -5717,6 +5761,7 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, handler = rtw89_mac_c2h_ap_handler[func]; break; case RTW89_MAC_C2H_CLASS_FWDBG: + case RTW89_MAC_C2H_CLASS_ROLE: return; default: rtw89_info(rtwdev, "MAC c2h class %d not support\n", class); @@ -6869,6 +6914,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .filter_model_addr = R_AX_FILTER_MODEL_ADDR, .indir_access_addr = R_AX_INDIR_ACCESS_ENTRY, .mem_base_addrs = rtw89_mac_mem_base_addrs_ax, + .mem_page_size = MAC_MEM_DUMP_PAGE_SIZE_AX, .rx_fltr = R_AX_RX_FLTR_OPT, .port_base = &rtw89_port_base_ax, .agg_len_ht = R_AX_AGG_LEN_HT_0, diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 8013c852d5be..b7fd4a0fdb84 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -8,7 +8,9 @@ #include "core.h" #include "reg.h" -#define MAC_MEM_DUMP_PAGE_SIZE 0x40000 +#define MAC_MEM_DUMP_PAGE_SIZE_AX 0x40000 +#define MAC_MEM_DUMP_PAGE_SIZE_BE 0x80000 + #define ADDR_CAM_ENT_SIZE 0x40 #define ADDR_CAM_ENT_SHORT_SIZE 0x20 #define BSSID_CAM_ENT_SIZE 0x08 @@ -469,6 +471,7 @@ enum rtw89_mac_c2h_class { RTW89_MAC_C2H_CLASS_MLO = 0xc, RTW89_MAC_C2H_CLASS_MRC = 0xe, RTW89_MAC_C2H_CLASS_AP = 0x18, + RTW89_MAC_C2H_CLASS_ROLE = 0x1b, RTW89_MAC_C2H_CLASS_MAX, }; @@ -969,6 +972,7 @@ struct rtw89_mac_gen_def { u32 filter_model_addr; u32 indir_access_addr; const u32 *mem_base_addrs; + u32 mem_page_size; u32 rx_fltr; const struct rtw89_port_reg *port_base; u32 agg_len_ht; diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index b9e046208424..a3ae1e654a98 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -112,6 +112,8 @@ static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, rtw89_vif_type_mapping(rtwvif_link, false); wiphy_work_init(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); + wiphy_delayed_work_init(&rtwvif_link->csa_beacon_work, rtw89_core_csa_beacon_work); + INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); rtw89_p2p_noa_once_init(rtwvif_link); @@ -144,6 +146,7 @@ static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev, lockdep_assert_wiphy(rtwdev->hw->wiphy); wiphy_work_cancel(rtwdev->hw->wiphy, &rtwvif_link->update_beacon_work); + wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwvif_link->csa_beacon_work); rtw89_p2p_noa_once_deinit(rtwvif_link); @@ -1356,6 +1359,73 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx); } +static +int rtw89_ops_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, + enum ieee80211_chanctx_switch_mode mode) +{ + struct rtw89_dev *rtwdev = hw->priv; + bool replace; + int ret; + int i; + + lockdep_assert_wiphy(hw->wiphy); + + switch (mode) { + case CHANCTX_SWMODE_REASSIGN_VIF: + replace = false; + break; + case CHANCTX_SWMODE_SWAP_CONTEXTS: + replace = true; + break; + default: + return -EOPNOTSUPP; + } + + for (i = 0; i < n_vifs; i++) { + struct ieee80211_vif_chanctx_switch *p = &vifs[i]; + struct ieee80211_bss_conf *link_conf = p->link_conf; + struct rtw89_vif *rtwvif = vif_to_rtwvif(p->vif); + struct rtw89_vif_link *rtwvif_link; + + 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 -ENOLINK; + } + + ret = rtw89_chanctx_ops_reassign_vif(rtwdev, rtwvif_link, + p->old_ctx, p->new_ctx, + replace); + if (ret) + return ret; + } + + return 0; +} + +static void rtw89_ops_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif_link *rtwvif_link; + + BUILD_BUG_ON(RTW89_MLD_NON_STA_LINK_NUM != 1); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "chsw bcn: find no link on HW-0\n"); + return; + } + + wiphy_delayed_work_queue(hw->wiphy, &rtwvif_link->csa_beacon_work, 0); +} + static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *chan, @@ -1700,13 +1770,13 @@ static int rtw89_ops_suspend(struct ieee80211_hw *hw, lockdep_assert_wiphy(hw->wiphy); - set_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + set_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags); wiphy_delayed_work_cancel(hw->wiphy, &rtwdev->track_work); ret = rtw89_wow_suspend(rtwdev, wowlan); if (ret) { rtw89_warn(rtwdev, "failed to suspend for wow %d\n", ret); - clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags); return 1; } @@ -1724,7 +1794,7 @@ static int rtw89_ops_resume(struct ieee80211_hw *hw) if (ret) rtw89_warn(rtwdev, "failed to resume for wow %d\n", ret); - clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags); wiphy_delayed_work_queue(hw->wiphy, &rtwdev->track_work, RTW89_TRACK_WORK_PERIOD); @@ -1807,6 +1877,8 @@ const struct ieee80211_ops rtw89_ops = { .change_chanctx = rtw89_ops_change_chanctx, .assign_vif_chanctx = rtw89_ops_assign_vif_chanctx, .unassign_vif_chanctx = rtw89_ops_unassign_vif_chanctx, + .switch_vif_chanctx = rtw89_ops_switch_vif_chanctx, + .channel_switch_beacon = rtw89_ops_channel_switch_beacon, .remain_on_channel = rtw89_ops_remain_on_channel, .cancel_remain_on_channel = rtw89_ops_cancel_remain_on_channel, .set_sar_specs = rtw89_ops_set_sar_specs, diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 8c9d326dc907..0078080b3999 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -2567,6 +2567,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .filter_model_addr = R_BE_FILTER_MODEL_ADDR, .indir_access_addr = R_BE_INDIR_ACCESS_ENTRY, .mem_base_addrs = rtw89_mac_mem_base_addrs_be, + .mem_page_size = MAC_MEM_DUMP_PAGE_SIZE_BE, .rx_fltr = R_BE_RX_FLTR_OPT, .port_base = &rtw89_port_base_be, .agg_len_ht = R_BE_AGG_LEN_HT_0, diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 064f6a940107..204a3748d913 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -4353,6 +4353,43 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev) SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume); EXPORT_SYMBOL(rtw89_pm_ops); +static pci_ers_result_t rtw89_pci_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + netif_device_detach(netdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t rtw89_pci_io_slot_reset(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw89_dev *rtwdev = hw->priv; + + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void rtw89_pci_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + /* ack any pending wake events, disable PME */ + pci_enable_wake(pdev, PCI_D0, 0); + + netif_device_attach(netdev); +} + +const struct pci_error_handlers rtw89_pci_err_handler = { + .error_detected = rtw89_pci_io_error_detected, + .slot_reset = rtw89_pci_io_slot_reset, + .resume = rtw89_pci_io_resume, +}; +EXPORT_SYMBOL(rtw89_pci_err_handler); + const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { .isr_rdu = B_AX_RDU_INT, .isr_halt_c2h = B_AX_HALT_C2H_INT_EN, diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 79fef5f90140..52f527069da6 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -1622,6 +1622,7 @@ static inline bool rtw89_pci_ltr_is_err_reg_val(u32 val) extern const struct dev_pm_ops rtw89_pm_ops; extern const struct dev_pm_ops rtw89_pm_ops_be; +extern const struct pci_error_handlers rtw89_pci_err_handler; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_v1; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be; diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 76a2e26d4a10..f81bee4149bf 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -119,10 +119,12 @@ 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_link_sta *link_sta) +static u64 get_eht_ra_mask(struct rtw89_vif_link *rtwvif_link, + struct ieee80211_link_sta *link_sta) { - struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; @@ -136,8 +138,8 @@ static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta) /* MCS 9, 11, 13 */ return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3); case IEEE80211_STA_RX_BW_20: - if (!(he_phy_cap[0] & - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { + if (vif->type == NL80211_IFTYPE_AP && + !(he_phy_cap[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz; /* MCS 7, 9, 11, 13 */ return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4); @@ -332,7 +334,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, /* Set the ra mask from sta's capability */ if (link_sta->eht_cap.has_eht) { mode |= RTW89_RA_MODE_EHT; - ra_mask |= get_eht_ra_mask(link_sta); + ra_mask |= get_eht_ra_mask(rtwvif_link, link_sta); if (rtwdev->hal.no_mcs_12_13) high_rate_masks = rtw89_ra_mask_eht_mcs0_11; @@ -5828,14 +5830,20 @@ void rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev) __rtw89_phy_env_monitor_track(rtwdev, bb); } -static bool rtw89_physts_ie_page_valid(enum rtw89_phy_status_bitmap *ie_page) +static bool rtw89_physts_ie_page_valid(struct rtw89_dev *rtwdev, + enum rtw89_phy_status_bitmap *ie_page) { + const struct rtw89_chip_info *chip = rtwdev->chip; + if (*ie_page >= RTW89_PHYSTS_BITMAP_NUM || *ie_page == RTW89_RSVD_9) return false; - else if (*ie_page > RTW89_RSVD_9) + else if (*ie_page > RTW89_RSVD_9 && *ie_page < RTW89_EHT_PKT) *ie_page -= 1; + if (*ie_page == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX) + return false; + return true; } @@ -5843,6 +5851,9 @@ static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page) { static const u8 ie_page_shift = 2; + if (ie_page == RTW89_EHT_PKT) + return R_PHY_STS_BITMAP_EHT; + return R_PHY_STS_BITMAP_ADDR_START + (ie_page << ie_page_shift); } @@ -5852,7 +5863,7 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, { u32 addr; - if (!rtw89_physts_ie_page_valid(&ie_page)) + if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page)) return 0; addr = rtw89_phy_get_ie_bitmap_addr(ie_page); @@ -5867,7 +5878,7 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, const struct rtw89_chip_info *chip = rtwdev->chip; u32 addr; - if (!rtw89_physts_ie_page_valid(&ie_page)) + if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page)) return; if (chip->chip_id == RTL8852A) @@ -5877,21 +5888,6 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, 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, enum rtw89_phy_idx phy_idx) -{ - 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, phy_idx); -} - static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, bool enable, enum rtw89_phy_idx phy_idx) @@ -5915,30 +5911,37 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 val; u8 i; 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, phy_idx); - if ((i >= RTW89_CCK_BRK && i <= RTW89_VHT_MU) || - (i >= RTW89_RSVD_9 && i <= RTW89_CCK_PKT)) + if (i == RTW89_RSVD_9 || + (i == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX)) continue; - rtw89_physts_enable_ie_bitmap(rtwdev, i, - RTW89_PHYSTS_IE24_OFDM_TD_PATH_A, - true, phy_idx); - } - rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_VHT_PKT, - 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, 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, phy_idx); + val = rtw89_physts_get_ie_bitmap(rtwdev, i, phy_idx); + if (i == RTW89_HE_MU || i == RTW89_VHT_MU) { + val |= BIT(RTW89_PHYSTS_IE13_DL_MU_DEF); + } else if (i == RTW89_TRIG_BASE_PPDU) { + val |= BIT(RTW89_PHYSTS_IE13_DL_MU_DEF) | + BIT(RTW89_PHYSTS_IE01_CMN_OFDM); + } else if (i >= RTW89_CCK_PKT) { + val |= BIT(RTW89_PHYSTS_IE09_FTR_0); + + val &= ~(GENMASK(RTW89_PHYSTS_IE07_CMN_EXT_PATH_D, + RTW89_PHYSTS_IE04_CMN_EXT_PATH_A)); + + if (i == RTW89_CCK_PKT) + val |= BIT(RTW89_PHYSTS_IE01_CMN_OFDM); + else if (i >= RTW89_HT_PKT) + val |= BIT(RTW89_PHYSTS_IE20_DBG_OFDM_FD_USER_SEG_0); + } + + rtw89_physts_set_ie_bitmap(rtwdev, i, val, phy_idx); + } } static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev) @@ -7125,7 +7128,7 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b const struct rtw89_edcca_p_regs *edcca_p_regs; bool flag_fb, flag_p20, flag_s20, flag_s40, flag_s80; s8 pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80; - u8 path, per20_bitmap; + u8 path, per20_bitmap = 0; u8 pwdb[8]; u32 tmp; @@ -7155,14 +7158,11 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b pwdb_fb = u32_get_bits(tmp, MASKBYTE3); rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel, - edcca_p_regs->rpt_sel_mask, 4); + edcca_p_regs->rpt_sel_mask, 5); tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b); pwdb_s80 = u32_get_bits(tmp, MASKBYTE1); pwdb_s40 = u32_get_bits(tmp, MASKBYTE2); - per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a, - MASKBYTE0); - if (rtwdev->chip->chip_id == RTL8922A) { rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, edcca_regs->rpt_sel_be_mask, 4); @@ -7171,6 +7171,8 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b pwdb[1] = u32_get_bits(tmp, MASKBYTE2); pwdb[2] = u32_get_bits(tmp, MASKBYTE1); pwdb[3] = u32_get_bits(tmp, MASKBYTE0); + per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a, + MASKBYTE0); rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, edcca_regs->rpt_sel_be_mask, 5); @@ -7187,7 +7189,7 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b pwdb[1] = u32_get_bits(tmp, MASKBYTE2); rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel, - edcca_p_regs->rpt_sel_mask, 1); + edcca_p_regs->rpt_sel_mask, 5); tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_a); pwdb[2] = u32_get_bits(tmp, MASKBYTE3); pwdb[3] = u32_get_bits(tmp, MASKBYTE2); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 5b451f1cfaac..63cc33c16c9a 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -252,6 +252,7 @@ enum rtw89_phy_status_bitmap { RTW89_HT_PKT = 13, RTW89_VHT_PKT = 14, RTW89_HE_PKT = 15, + RTW89_EHT_PKT = 16, RTW89_PHYSTS_BITMAP_NUM }; diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index 8e4fe73e7d77..3411d642c84a 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -137,6 +137,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, can_ps_mode = false; } + rtw89_fw_h2c_rf_ps_info(rtwdev, rtwvif); + if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw)) rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); else @@ -236,13 +238,23 @@ static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false); } -static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct ieee80211_bss_conf *bss_conf) +void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { enum rtw89_p2pps_action act; + u8 oppps_ctwindow; u8 noa_id; + rcu_read_lock(); + + if (!bss_conf) + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + oppps_ctwindow = bss_conf->p2p_noa_attr.oppps_ctwindow; + + rcu_read_unlock(); + if (rtwvif_link->last_noa_nr == 0) return; @@ -252,8 +264,8 @@ static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, else act = RTW89_P2P_ACT_REMOVE; rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); - rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, - NULL, act, noa_id); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, NULL, + act, noa_id, oppps_ctwindow); } } @@ -275,8 +287,8 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, else act = RTW89_P2P_ACT_UPDATE; rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); - rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, - desc, act, noa_id); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, desc, act, noa_id, + bss_conf->p2p_noa_attr.oppps_ctwindow); } rtwvif_link->last_noa_nr = noa_id; } diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index b2c43d44820d..729477153de6 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -25,6 +25,9 @@ u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data); void rtw89_p2p_noa_once_init(struct rtw89_vif_link *rtwvif_link); void rtw89_p2p_noa_once_deinit(struct rtw89_vif_link *rtwvif_link); void rtw89_p2p_noa_once_recalc(struct rtw89_vif_link *rtwvif_link); +void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf); static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) { diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index f05c81ae5869..4a65b0c9c2d1 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -6070,6 +6070,7 @@ #define B_BE_MACID_ACQ_GRP0_CLR_P BIT(2) #define B_BE_R_MACID_ACQ_CHK_EN BIT(0) +#define R_BE_BTC_CFG 0x0E300 #define R_BE_BT_BREAK_TABLE 0x0E344 #define R_BE_GNT_SW_CTRL 0x0E348 @@ -8024,6 +8025,7 @@ #define R_PHY_STS_BITMAP_HT 0x076C #define R_PHY_STS_BITMAP_VHT 0x0770 #define R_PHY_STS_BITMAP_HE 0x0774 +#define R_PHY_STS_BITMAP_EHT 0x0788 #define R_EDCCA_RPTREG_SEL_BE 0x078C #define B_EDCCA_RPTREG_SEL_BE_MSK GENMASK(22, 20) #define R_PMAC_GNT 0x0980 diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index fafa200a9c8d..c55833f259de 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2402,6 +2402,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl, .init_txpwr_unit = rtw8851b_init_txpwr_unit, .get_thermal = rtw8851b_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8851b_ctrl_btg_bt_rx, .query_ppdu = rtw8851b_query_ppdu, .convert_rpl_to_rssi = NULL, @@ -2528,7 +2529,6 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .phycap_size = 128, .para_ver = 0, .wlcx_desired = 0x06000000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c index 5810af825242..598730831707 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c @@ -89,6 +89,7 @@ static struct pci_driver rtw89_8851be_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8851be_driver); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index cd5987fc52d7..080636e8d0c3 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2128,6 +2128,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .set_txpwr_ctrl = rtw8852a_set_txpwr_ctrl, .init_txpwr_unit = rtw8852a_init_txpwr_unit, .get_thermal = rtw8852a_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852a_ctrl_btg_bt_rx, .query_ppdu = rtw8852a_query_ppdu, .convert_rpl_to_rssi = NULL, @@ -2246,7 +2247,6 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .phycap_size = 128, .para_ver = 0x0, .wlcx_desired = 0x06000000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c index 2037713e3952..90ffaf9f4f6a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c @@ -91,6 +91,7 @@ static struct pci_driver rtw89_8852ae_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8852ae_driver); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index dacdb384de2c..c0bf80450acf 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -755,6 +755,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .set_txpwr_ctrl = rtw8852bx_set_txpwr_ctrl, .init_txpwr_unit = rtw8852bx_init_txpwr_unit, .get_thermal = rtw8852bx_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, @@ -882,7 +883,6 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .phycap_size = 128, .para_ver = 0, .wlcx_desired = 0x05050000, - .btcx_desired = 0x5, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852be.c b/drivers/net/wireless/realtek/rtw89/rtw8852be.c index abdeafc14b0b..b0726f590ca2 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852be.c @@ -93,6 +93,7 @@ static struct pci_driver rtw89_8852be_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8852be_driver); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index 289dce688d72..95e088734423 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -689,6 +689,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .set_txpwr_ctrl = rtw8852bx_set_txpwr_ctrl, .init_txpwr_unit = rtw8852bx_init_txpwr_unit, .get_thermal = rtw8852bx_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, @@ -815,7 +816,6 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .phycap_size = 128, .para_ver = 0, .wlcx_desired = 0x070e0000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c index b69fa17beb33..a584c75b801d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c @@ -95,6 +95,7 @@ static struct pci_driver rtw89_8852bte_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8852bte_driver); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 2a6143a8d256..8f3d0c91a3f8 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2948,6 +2948,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl, .init_txpwr_unit = rtw8852c_init_txpwr_unit, .get_thermal = rtw8852c_get_thermal, + .chan_to_rf18_val = NULL, .ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx, .query_ppdu = rtw8852c_query_ppdu, .convert_rpl_to_rssi = NULL, @@ -3069,7 +3070,6 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .phycap_size = 0x60, .para_ver = 0x1, .wlcx_desired = 0x06000000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c index 5d864fd5974e..db01d3966c27 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c @@ -118,6 +118,7 @@ static struct pci_driver rtw89_8852ce_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8852ce_driver); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 1d0f6e7df497..603212ed4558 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -15,7 +15,7 @@ #include "sar.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 3 +#define RTW8922A_FW_FORMAT_MAX 4 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" @@ -2390,6 +2390,48 @@ static u8 rtw8922a_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p return clamp_t(int, th, 0, U8_MAX); } +static u32 rtw8922a_chan_to_rf18_val(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u32 val = u32_encode_bits(chan->channel, RR_CFGCH_CH); + + switch (chan->band_type) { + case RTW89_BAND_2G: + default: + break; + case RTW89_BAND_5G: + val |= u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0); + break; + case RTW89_BAND_6G: + val |= u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0); + break; + } + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_5: + case RTW89_CHANNEL_WIDTH_10: + case RTW89_CHANNEL_WIDTH_20: + default: + break; + case RTW89_CHANNEL_WIDTH_40: + val |= u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_80: + val |= u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_160: + val |= u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_320: + val |= u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2); + break; + } + + return val; +} + static void rtw8922a_btc_set_rfe(struct rtw89_dev *rtwdev) { union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; @@ -2761,6 +2803,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .set_txpwr_ctrl = rtw8922a_set_txpwr_ctrl, .init_txpwr_unit = NULL, .get_thermal = rtw8922a_get_thermal, + .chan_to_rf18_val = rtw8922a_chan_to_rf18_val, .ctrl_btg_bt_rx = rtw8922a_ctrl_btg_bt_rx, .query_ppdu = rtw8922a_query_ppdu, .convert_rpl_to_rssi = rtw8922a_convert_rpl_to_rssi, @@ -2880,7 +2923,6 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .phycap_size = 0x38, .para_ver = 0xf, .wlcx_desired = 0x07110000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c index 1659ea64ade1..fce094c7ce93 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c @@ -36,8 +36,7 @@ void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx) static void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, - u8 central_ch, enum rtw89_band band, - enum rtw89_bandwidth bw) + const struct rtw89_chan *chan) { const u32 rf_addr[2] = {RR_CFGCH, RR_CFGCH_V1}; struct rtw89_hal *hal = &rtwdev->hal; @@ -73,49 +72,9 @@ void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, return; } - rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW | + rf_reg[path][i] &= ~(RR_CFGCH_BAND1 | RR_CFGCH_BW_V2 | RR_CFGCH_BAND0 | RR_CFGCH_CH); - rf_reg[path][i] |= u32_encode_bits(central_ch, RR_CFGCH_CH); - - switch (band) { - case RTW89_BAND_2G: - default: - break; - case RTW89_BAND_5G: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) | - u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0); - break; - case RTW89_BAND_6G: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) | - u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0); - break; - } - - switch (bw) { - case RTW89_CHANNEL_WIDTH_5: - case RTW89_CHANNEL_WIDTH_10: - case RTW89_CHANNEL_WIDTH_20: - default: - break; - case RTW89_CHANNEL_WIDTH_40: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_80: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_160: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2); - break; - case RTW89_CHANNEL_WIDTH_320: - rf_reg[path][i] |= - u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2); - break; - } + rf_reg[path][i] |= rtw89_chip_chan_to_rf18_val(rtwdev, chan); rtw89_write_rf(rtwdev, path, rf_addr[i], RFREG_MASK, rf_reg[path][i]); @@ -126,7 +85,7 @@ void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, if (hal->cv != CHIP_CAV) return; - if (band == RTW89_BAND_2G) { + if (chan->band_type == RTW89_BAND_2G) { rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000); rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x00003); rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c990); @@ -145,8 +104,7 @@ void rtw8922a_set_channel_rf(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { - rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan->channel, chan->band_type, - chan->band_width); + rtw8922a_ctl_band_ch_bw(rtwdev, phy_idx, chan); } enum _rf_syn_pow { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c index 0ea8d5281c10..b730d79edd10 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c @@ -106,6 +106,7 @@ static struct pci_driver rtw89_8922ae_driver = { .probe = rtw89_pci_probe, .remove = rtw89_pci_remove, .driver.pm = &rtw89_pm_ops_be, + .err_handler = &rtw89_pci_err_handler, }; module_pci_driver(rtw89_8922ae_driver); diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index 517b66022f18..7f568ffb3766 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -199,7 +199,8 @@ struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = { typeof(_dev) _d = (_dev); \ BUILD_BUG_ON(!rtw89_sar_handlers[_s].descr_sar_source); \ BUILD_BUG_ON(!rtw89_sar_handlers[_s].query_sar_config); \ - lockdep_assert_wiphy(_d->hw->wiphy); \ + if (test_bit(RTW89_FLAG_PROBE_DONE, _d->flags)) \ + lockdep_assert_wiphy(_d->hw->wiphy); \ _d->sar._cfg_name = *(_cfg_data); \ _d->sar.src = _s; \ } while (0) @@ -499,8 +500,6 @@ static void rtw89_set_sar_from_acpi(struct rtw89_dev *rtwdev) struct rtw89_sar_cfg_acpi *cfg; int ret; - lockdep_assert_wiphy(rtwdev->hw->wiphy); - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) return; diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 811c91481441..d504518b8a57 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -566,21 +566,22 @@ static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf, const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u32 filter_model_addr = mac->filter_model_addr; u32 indir_access_addr = mac->indir_access_addr; + u32 mem_page_size = mac->mem_page_size; u32 *ptr = (u32 *)buf; u32 base_addr, start_page, residue; u32 cnt = 0; u32 i; - start_page = start_addr / MAC_MEM_DUMP_PAGE_SIZE; - residue = start_addr % MAC_MEM_DUMP_PAGE_SIZE; + start_page = start_addr / mem_page_size; + residue = start_addr % mem_page_size; base_addr = mac->mem_base_addrs[sel]; - base_addr += start_page * MAC_MEM_DUMP_PAGE_SIZE; + base_addr += start_page * mem_page_size; while (cnt < len) { rtw89_write32(rtwdev, filter_model_addr, base_addr); for (i = indir_access_addr + residue; - i < indir_access_addr + MAC_MEM_DUMP_PAGE_SIZE; + i < indir_access_addr + mem_page_size; i += 4, ptr++) { *ptr = rtw89_read32(rtwdev, i); cnt += 4; @@ -589,7 +590,7 @@ static void ser_mac_mem_dump(struct rtw89_dev *rtwdev, u8 *buf, } residue = 0; - base_addr += MAC_MEM_DUMP_PAGE_SIZE; + base_addr += mem_page_size; } } |