diff options
author | 2024-12-13 14:57:06 +0200 | |
---|---|---|
committer | 2024-12-13 14:57:06 +0200 | |
commit | 104372ff359486b26b5a2db33b8e1dc6bfb39812 (patch) | |
tree | 2d4d687cede3c0dc20a1426a19a814301c91d9da | |
parent | wifi: brcmfmac: add missing header include for brcmf_dbg (diff) | |
parent | wifi: rtw89: phy: add dummy C2H event handler for report of TAS power (diff) | |
download | wireguard-linux-104372ff359486b26b5a2db33b8e1dc6bfb39812.tar.xz wireguard-linux-104372ff359486b26b5a2db33b8e1dc6bfb39812.zip |
Merge tag 'rtw-next-2024-12-12' of https://github.com/pkshih/rtw
rtw-next patches for v6.14
Regular development in this period. Main changes are listed:
rtl8xxxu:
* add more USB devices IDs
rtlwifi:
* refine error path
rtw88:
* add more USB devices IDs
* enable USB RX aggregation and USB 3 to improve performance
rtw89:
* implement more stuffs including PS flow for MLO
47 files changed, 1840 insertions, 358 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c index f95898f68d68..4ce0c05c5129 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -8147,6 +8147,8 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8186, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), @@ -8157,12 +8159,18 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x11f2, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8188, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9043, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff), @@ -8179,6 +8187,10 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3358, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3359, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff), @@ -8193,6 +8205,8 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x9846, 0x9041, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), @@ -8218,6 +8232,8 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff), @@ -8226,6 +8242,8 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0077, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff), @@ -8248,6 +8266,8 @@ static const struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index aab4605de9c4..ff61867d142f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -575,9 +575,15 @@ static void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw, void rtl_deinit_core(struct ieee80211_hw *hw) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_c2hcmd_launcher(hw, 0); rtl_free_entries_from_scan_list(hw); rtl_free_entries_from_ack_queue(hw, false); + if (rtlpriv->works.rtl_wq) { + destroy_workqueue(rtlpriv->works.rtl_wq); + rtlpriv->works.rtl_wq = NULL; + } } EXPORT_SYMBOL_GPL(rtl_deinit_core); @@ -2696,9 +2702,6 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); -struct rtl_global_var rtl_global_var = {}; -EXPORT_SYMBOL_GPL(rtl_global_var); - static int __init rtl_core_module_init(void) { BUILD_BUG_ON(TX_PWR_BY_RATE_NUM_RATE < TX_PWR_BY_RATE_NUM_SECTION); @@ -2712,10 +2715,6 @@ static int __init rtl_core_module_init(void) /* add debugfs */ rtl_debugfs_add_topdir(); - /* init some global vars */ - INIT_LIST_HEAD(&rtl_global_var.glb_priv_list); - spin_lock_init(&rtl_global_var.glb_list_lock); - return 0; } diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index f081a9a90563..f3a6a43a42ec 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(u8 tid); -extern struct rtl_global_var rtl_global_var; void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 11709b6c83f1..0eafc4d125f9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -295,46 +295,6 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) return status; } -static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, - struct rtl_priv **buddy_priv) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_priv *tpriv = NULL, *iter; - struct rtl_pci_priv *tpcipriv = NULL; - - if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { - list_for_each_entry(iter, &rtlpriv->glb_var->glb_priv_list, - list) { - tpcipriv = (struct rtl_pci_priv *)iter->priv; - rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, - "pcipriv->ndis_adapter.funcnumber %x\n", - pcipriv->ndis_adapter.funcnumber); - rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, - "tpcipriv->ndis_adapter.funcnumber %x\n", - tpcipriv->ndis_adapter.funcnumber); - - if (pcipriv->ndis_adapter.busnumber == - tpcipriv->ndis_adapter.busnumber && - pcipriv->ndis_adapter.devnumber == - tpcipriv->ndis_adapter.devnumber && - pcipriv->ndis_adapter.funcnumber != - tpcipriv->ndis_adapter.funcnumber) { - tpriv = iter; - break; - } - } - } - - rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, - "find_buddy_priv %d\n", tpriv != NULL); - - if (tpriv) - *buddy_priv = tpriv; - - return tpriv != NULL; -} - static void rtl_pci_parse_configuration(struct pci_dev *pdev, struct ieee80211_hw *hw) { @@ -1696,8 +1656,6 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) synchronize_irq(rtlpci->pdev->irq); tasklet_kill(&rtlpriv->works.irq_tasklet); cancel_work_sync(&rtlpriv->works.lps_change_work); - - destroy_workqueue(rtlpriv->works.rtl_wq); } static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) @@ -2011,7 +1969,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, pcipriv->ndis_adapter.amd_l1_patch); rtl_pci_parse_configuration(pdev, hw); - list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); return true; } @@ -2158,7 +2115,6 @@ int rtl_pci_probe(struct pci_dev *pdev, rtlpriv->rtlhal.interface = INTF_PCI; rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); rtlpriv->intf_ops = &rtl_pci_ops; - rtlpriv->glb_var = &rtl_global_var; rtl_efuse_ops_init(hw); /* MEM map */ @@ -2209,7 +2165,7 @@ int rtl_pci_probe(struct pci_dev *pdev, if (rtlpriv->cfg->ops->init_sw_vars(hw)) { pr_err("Can't init_sw_vars\n"); err = -ENODEV; - goto fail3; + goto fail2; } rtl_init_sw_leds(hw); @@ -2227,14 +2183,14 @@ int rtl_pci_probe(struct pci_dev *pdev, err = rtl_pci_init(hw, pdev); if (err) { pr_err("Failed to init PCI\n"); - goto fail3; + goto fail4; } err = ieee80211_register_hw(hw); if (err) { pr_err("Can't register mac80211 hw.\n"); err = -ENODEV; - goto fail3; + goto fail5; } rtlpriv->mac80211.mac80211_registered = 1; @@ -2257,16 +2213,19 @@ int rtl_pci_probe(struct pci_dev *pdev, set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); return 0; -fail3: - pci_set_drvdata(pdev, NULL); +fail5: + rtl_pci_deinit(hw); +fail4: rtl_deinit_core(hw); +fail3: + wait_for_completion(&rtlpriv->firmware_loading_complete); + rtlpriv->cfg->ops->deinit_sw_vars(hw); fail2: if (rtlpriv->io.pci_mem_start != 0) pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); pci_release_regions(pdev); - complete(&rtlpriv->firmware_loading_complete); fail1: if (hw) @@ -2317,7 +2276,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) if (rtlpci->using_msi) pci_disable_msi(rtlpci->pdev); - list_del(&rtlpriv->list); if (rtlpriv->io.pci_mem_start != 0) { pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); pci_release_regions(pdev); @@ -2376,7 +2334,6 @@ EXPORT_SYMBOL(rtl_pci_resume); const struct rtl_intf_ops rtl_pci_ops = { .adapter_start = rtl_pci_start, .adapter_stop = rtl_pci_stop, - .check_buddy_priv = rtl_pci_check_buddy_priv, .adapter_tx = rtl_pci_tx, .flush = rtl_pci_flush, .reset_trx_ring = rtl_pci_reset_trx_ring, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index bbf8ff63dced..e63c67b1861b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -64,22 +64,23 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context) rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, "Firmware callback routine entered!\n"); - complete(&rtlpriv->firmware_loading_complete); if (!firmware) { pr_err("Firmware %s not available\n", fw_name); rtlpriv->max_fw_size = 0; - return; + goto exit; } if (firmware->size > rtlpriv->max_fw_size) { pr_err("Firmware is too big!\n"); rtlpriv->max_fw_size = 0; release_firmware(firmware); - return; + goto exit; } pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); pfirmware->sz_fw_tmpbufferlen = firmware->size; release_firmware(firmware); +exit: + complete(&rtlpriv->firmware_loading_complete); } static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 1be51ea3f3c8..9eddbada8af1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -2033,8 +2033,10 @@ static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, if (!_rtl8821ae_check_condition(hw, v1)) { i += 2; /* skip the pair of expression*/ v2 = array[i+1]; - while (v2 != 0xDEAD) + while (v2 != 0xDEAD) { i += 3; + v2 = array[i + 1]; + } } } } diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index d37a017b2b81..f5718e570011 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -629,11 +629,6 @@ static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) tasklet_kill(&rtlusb->rx_work_tasklet); cancel_work_sync(&rtlpriv->works.lps_change_work); - if (rtlpriv->works.rtl_wq) { - destroy_workqueue(rtlpriv->works.rtl_wq); - rtlpriv->works.rtl_wq = NULL; - } - skb_queue_purge(&rtlusb->rx_queue); while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { @@ -1028,19 +1023,22 @@ int rtl_usb_probe(struct usb_interface *intf, err = ieee80211_register_hw(hw); if (err) { pr_err("Can't register mac80211 hw.\n"); - goto error_out; + goto error_init_vars; } rtlpriv->mac80211.mac80211_registered = 1; set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); return 0; +error_init_vars: + wait_for_completion(&rtlpriv->firmware_loading_complete); + rtlpriv->cfg->ops->deinit_sw_vars(hw); error_out: + rtl_usb_deinit(hw); rtl_deinit_core(hw); error_out2: _rtl_usb_io_handler_release(hw); usb_put_dev(udev); - complete(&rtlpriv->firmware_loading_complete); kfree(rtlpriv->usb_data); ieee80211_free_hw(hw); return -ENODEV; diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index ae6e351bc83c..f1830ddcdd8c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2270,8 +2270,6 @@ struct rtl_intf_ops { /*com */ int (*adapter_start)(struct ieee80211_hw *hw); void (*adapter_stop)(struct ieee80211_hw *hw); - bool (*check_buddy_priv)(struct ieee80211_hw *hw, - struct rtl_priv **buddy_priv); int (*adapter_tx)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, @@ -2514,14 +2512,6 @@ struct dig_t { u32 rssi_max; }; -struct rtl_global_var { - /* from this list we can get - * other adapter's rtl_priv - */ - struct list_head glb_priv_list; - spinlock_t glb_list_lock; -}; - #define IN_4WAY_TIMEOUT_TIME (30 * MSEC_PER_SEC) /* 30 seconds */ struct rtl_btc_info { @@ -2667,9 +2657,7 @@ struct rtl_scan_list { struct rtl_priv { struct ieee80211_hw *hw; struct completion firmware_loading_complete; - struct list_head list; struct rtl_priv *buddy_priv; - struct rtl_global_var *glb_var; struct rtl_dmsp_ctl dmsp_ctl; struct rtl_locks locks; struct rtl_works works; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c index 4da69590a423..e18995f4cc78 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8812au.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c @@ -9,8 +9,74 @@ #include "usb.h" static const struct usb_device_id rtw_8812au_id_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff), + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8812, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881b, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881c, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0409, 0x0408, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* NEC */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x025d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Buffalo */ + { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0952, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* I-O DATA */ + { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1106, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */ + { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1109, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x3426, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ZyXEL */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016e, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Logitec */ + { USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8812, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Abocom */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9051, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Netgear */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17d2, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ASUS */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0074, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Sitecom */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0022, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Hawking */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0632, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* WD */ + { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x003f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Linksys */ + { USB_DEVICE_AND_INTERFACE_INFO(0x148f, 0x9097, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Amped Wireless */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1740, 0x0100, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* EnGenius */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330e, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3313, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3315, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3316, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab30, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Planex */ + { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TRENDnet */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0101, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0103, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010e, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0122, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Tenda */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa822, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Edimax */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c index 730018773e1c..a01744b64e8d 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821au.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c @@ -9,8 +9,58 @@ #include "usb.h" static const struct usb_device_id rtw_8821au_id_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff), + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0820, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0821, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8822, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0823, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xa811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x0242, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x029b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */ + { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0953, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* I-O DATA */ + { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4007, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ + { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400e, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ + { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9052, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Netgear */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0023, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* HAWKING */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3314, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3318, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab32, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Planex */ + { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x804b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TRENDnet */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0120, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x3823, 0x6249, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Obihai */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa812, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa813, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb611, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c index ab620a0b1dfc..8883300fc6ad 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c @@ -67,6 +67,12 @@ static const struct usb_device_id rtw_8822bu_id_table[] = { .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */ + { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-805UBH */ + { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4011, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ELECOM WDB-867DU3S */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0107, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30H */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 8d6db68246f1..be193c7add77 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -789,6 +789,30 @@ static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable) rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16); } +static void rtw_usb_dynamic_rx_agg_v2(struct rtw_dev *rtwdev, bool enable) +{ + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); + u8 size, timeout; + u16 val16; + + if (!enable) { + size = 0x0; + timeout = 0x1; + } else if (rtwusb->udev->speed == USB_SPEED_SUPER) { + size = 0x6; + timeout = 0x1a; + } else { + size = 0x5; + timeout = 0x20; + } + + val16 = u16_encode_bits(size, BIT_RXDMA_AGG_PG_TH) | + u16_encode_bits(timeout, BIT_DMA_AGG_TO_V1); + + rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16); + rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN); +} + static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) { switch (rtwdev->chip->id) { @@ -797,6 +821,10 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) case RTW_CHIP_TYPE_8821C: rtw_usb_dynamic_rx_agg_v1(rtwdev, enable); break; + case RTW_CHIP_TYPE_8821A: + case RTW_CHIP_TYPE_8812A: + rtw_usb_dynamic_rx_agg_v2(rtwdev, enable); + break; case RTW_CHIP_TYPE_8723D: /* Doesn't like aggregation. */ break; @@ -930,6 +958,32 @@ static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev, usb_set_intfdata(intf, NULL); } +static int rtw_usb_switch_mode_old(struct rtw_dev *rtwdev) +{ + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); + enum usb_device_speed cur_speed = rtwusb->udev->speed; + u8 hci_opt; + + if (cur_speed == USB_SPEED_HIGH) { + hci_opt = rtw_read8(rtwdev, REG_HCI_OPT_CTRL); + + if ((hci_opt & (BIT(2) | BIT(3))) != BIT(3)) { + rtw_write8(rtwdev, REG_HCI_OPT_CTRL, 0x8); + rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x2); + rtw_write8(rtwdev, REG_ACLK_MON, 0x1); + rtw_write8(rtwdev, 0x3d, 0x3); + /* usb disconnect */ + rtw_write8(rtwdev, REG_SYS_PW_CTRL + 1, 0x80); + return 1; + } + } else if (cur_speed == USB_SPEED_SUPER) { + rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT(1)); + rtw_write8_clr(rtwdev, REG_ACLK_MON, BIT(0)); + } + + return 0; +} + static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev) { enum usb_device_speed cur_speed; @@ -979,11 +1033,22 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev) return 1; } +static bool rtw_usb3_chip_old(u8 chip_id) +{ + return chip_id == RTW_CHIP_TYPE_8812A; +} + +static bool rtw_usb3_chip_new(u8 chip_id) +{ + return chip_id == RTW_CHIP_TYPE_8822C || + chip_id == RTW_CHIP_TYPE_8822B; +} + static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) { u8 id = rtwdev->chip->id; - if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B) + if (!rtw_usb3_chip_new(id) && !rtw_usb3_chip_old(id)) return 0; if (!rtwdev->efuse.usb_mode_switch) { @@ -998,7 +1063,10 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) return 0; } - return rtw_usb_switch_mode_new(rtwdev); + if (rtw_usb3_chip_old(id)) + return rtw_usb_switch_mode_old(rtwdev); + else + return rtw_usb_switch_mode_new(rtwdev); } int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c index 908e980a4b72..f5dedb12c129 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.c +++ b/drivers/net/wireless/realtek/rtw89/acpi.c @@ -148,3 +148,50 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, ACPI_FREE(obj); return ret; } + +int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev, + struct rtw89_acpi_rtag_result *res) +{ + struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_handle root, handle; + union acpi_object *obj; + acpi_status status; + u32 buf_len; + int ret = 0; + + root = ACPI_HANDLE(rtwdev->dev); + if (!root) + return -EOPNOTSUPP; + + status = acpi_get_handle(root, (acpi_string)"RTAG", &handle); + if (ACPI_FAILURE(status)) + return -EIO; + + status = acpi_evaluate_object(handle, NULL, NULL, &buf); + if (ACPI_FAILURE(status)) + return -EIO; + + obj = buf.pointer; + if (obj->type != ACPI_TYPE_BUFFER) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, + "acpi: expect buffer but type: %d\n", obj->type); + ret = -EINVAL; + goto out; + } + + buf_len = obj->buffer.length; + if (buf_len != sizeof(*res)) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n", + __func__, buf_len); + ret = -EINVAL; + goto out; + } + + *res = *(struct rtw89_acpi_rtag_result *)obj->buffer.pointer; + + rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res)); + +out: + ACPI_FREE(obj); + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h index d274be1775bf..b43ab106e44d 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.h +++ b/drivers/net/wireless/realtek/rtw89/acpi.h @@ -63,8 +63,17 @@ struct rtw89_acpi_dsm_result { } u; }; +struct rtw89_acpi_rtag_result { + u8 tag[4]; + u8 revision; + __le32 domain; + u8 ant_gain_table[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR]; +} __packed; + int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, enum rtw89_acpi_dsm_func func, struct rtw89_acpi_dsm_result *res); +int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev, + struct rtw89_acpi_rtag_result *res); #endif diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 8ef59994c0db..8fa1e6c1ce13 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -135,8 +135,8 @@ again: } static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam, - struct rtw89_sec_cam_entry *sec_cam, - struct ieee80211_key_conf *key, + const struct rtw89_sec_cam_entry *sec_cam, + const struct ieee80211_key_conf *key, u8 *key_idx) { u8 idx; @@ -246,8 +246,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, - struct ieee80211_key_conf *key, - struct rtw89_sec_cam_entry *sec_cam) + const struct ieee80211_key_conf *key, + const struct rtw89_sec_cam_entry *sec_cam) { struct rtw89_addr_cam_entry *addr_cam; u8 key_idx = 0; @@ -286,6 +286,22 @@ static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, return 0; } +int rtw89_cam_attach_link_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + u8 sec_cam_idx) +{ + struct rtw89_cam_info *cam_info = &rtwdev->cam_info; + const struct rtw89_sec_cam_entry *sec_cam; + + sec_cam = cam_info->sec_entries[sec_cam_idx]; + if (!sec_cam) + return -ENOENT; + + return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, rtwsta_link, + sec_cam->key_conf, sec_cam); +} + static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -306,6 +322,9 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, rtwvif = vif_to_rtwvif(vif); + if (rtwsta) + clear_bit(sec_cam->sec_cam_idx, rtwsta->pairwise_sec_cam_map); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL; if (rtwsta && !rtwsta_link) @@ -369,6 +388,8 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, return ret; } + set_bit(sec_cam->sec_cam_idx, rtwsta->pairwise_sec_cam_map); + return 0; } @@ -410,6 +431,9 @@ static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev, sec_cam->len = RTW89_SEC_CAM_LEN; sec_cam->ext_key = ext_key; memcpy(sec_cam->key, key->key, key->keylen); + + sec_cam->key_conf = key; + ret = rtw89_cam_send_sec_key_cmd(rtwdev, sec_cam); if (ret) { rtw89_err(rtwdev, "failed to send sec key cmd: %d\n", ret); diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index 3134ebf08825..8fd2d776408e 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -578,4 +578,9 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev); +int rtw89_cam_attach_link_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + u8 sec_cam_idx); + #endif diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index e5b2968c1431..f848185e2ced 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -203,6 +203,55 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = { }, }; +#define RTW89_6GHZ_SPAN_HEAD 6145 +#define RTW89_6GHZ_SPAN_IDX(center_freq) \ + ((((int)(center_freq) - RTW89_6GHZ_SPAN_HEAD) / 5) / 2) + +#define RTW89_DECL_6GHZ_SPAN(center_freq, subband_l, subband_h) \ + [RTW89_6GHZ_SPAN_IDX(center_freq)] = { \ + .sar_subband_low = RTW89_SAR_6GHZ_ ## subband_l, \ + .sar_subband_high = RTW89_SAR_6GHZ_ ## subband_h, \ + .ant_gain_subband_low = RTW89_ANT_GAIN_6GHZ_ ## subband_l, \ + .ant_gain_subband_high = RTW89_ANT_GAIN_6GHZ_ ## subband_h, \ + } + +/* Since 6GHz subbands are not edge aligned, some cases span two subbands. + * In the following, we describe each of them with rtw89_6ghz_span. + */ +static const struct rtw89_6ghz_span rtw89_overlapping_6ghz[] = { + RTW89_DECL_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H), + RTW89_DECL_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H), + RTW89_DECL_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8), +}; + +const struct rtw89_6ghz_span * +rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq) +{ + int idx; + + if (center_freq >= RTW89_6GHZ_SPAN_HEAD) { + idx = RTW89_6GHZ_SPAN_IDX(center_freq); + /* To decrease size of rtw89_overlapping_6ghz[], + * RTW89_6GHZ_SPAN_IDX() truncates the leading NULLs + * to make first span as index 0 of the table. So, if center + * frequency is less than the first one, it will get netative. + */ + if (idx >= 0 && idx < ARRAY_SIZE(rtw89_overlapping_6ghz)) + return &rtw89_overlapping_6ghz[idx]; + } + + return NULL; +} + bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate) { struct ieee80211_rate rate; @@ -2140,6 +2189,8 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, if (phy_ppdu) ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg); + + pkt_stat->beacon_rate = desc_info->data_rate; } if (!ether_addr_equal(bss_conf->addr, hdr->addr1)) @@ -2317,6 +2368,12 @@ static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev, } } +static void rtw89_core_validate_rx_signal(struct ieee80211_rx_status *rx_status) +{ + if (!rx_status->signal) + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; +} + 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, @@ -2333,6 +2390,8 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, rtw89_core_rx_stats(rtwdev, phy_ppdu, desc_info, skb_ppdu); rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu); rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status); + rtw89_core_validate_rx_signal(rx_status); + /* In low power mode, it does RX in thread context. */ local_bh_disable(); ieee80211_rx_napi(rtwdev->hw, NULL, skb_ppdu, napi); @@ -2468,6 +2527,7 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, u8 *data, u32 data_offset) { + struct rtw89_rxdesc_phy_rpt_v2 *rxd_rpt; struct rtw89_rxdesc_short_v2 *rxd_s; struct rtw89_rxdesc_long_v2 *rxd_l; u16 shift_len, drv_info_len, phy_rtp_len, hdr_cnv_len; @@ -2515,6 +2575,12 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev, desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short_v2); desc_info->ready = true; + if (phy_rtp_len == sizeof(*rxd_rpt)) { + rxd_rpt = (struct rtw89_rxdesc_phy_rpt_v2 *)(data + data_offset + + desc_info->rxd_len); + desc_info->rssi = le32_get_bits(rxd_rpt->dword0, BE_RXD_PHY_RSSI); + } + if (!desc_info->long_rxdesc) return; @@ -2657,6 +2723,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rx_status->flag |= RX_FLAG_MACTIME_START; rx_status->mactime = desc_info->free_run_cnt; + rtw89_chip_phy_rpt_to_rssi(rtwdev, desc_info, rx_status); rtw89_core_stats_sta_rx_status(rtwdev, desc_info, rx_status); } @@ -2664,10 +2731,6 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */ - if (rtwdev->support_mlo) - return RTW89_PS_MODE_NONE; - if (rtw89_disable_ps_mode || !chip->ps_mode_supported || RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) return RTW89_PS_MODE_NONE; @@ -2700,6 +2763,41 @@ static void rtw89_core_flush_ppdu_rx_queue(struct rtw89_dev *rtwdev, } } +static +void rtw89_core_rx_pkt_hdl(struct rtw89_dev *rtwdev, const struct sk_buff *skb, + const struct rtw89_rx_desc_info *desc) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtw89_sta_link *rtwsta_link; + struct ieee80211_sta *sta; + struct rtw89_sta *rtwsta; + u8 macid = desc->mac_id; + + if (!refcount_read(&rtwdev->refcount_ap_info)) + return; + + rcu_read_lock(); + + rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, macid); + if (!rtwsta_link) + goto out; + + rtwsta = rtwsta_link->rtwsta; + if (!test_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags)) + goto out; + + sta = rtwsta_to_sta(rtwsta); + if (ieee80211_is_pspoll(hdr->frame_control)) + ieee80211_sta_pspoll(sta); + else if (ieee80211_has_pm(hdr->frame_control) && + (ieee80211_is_data_qos(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control))) + ieee80211_sta_uapsd_trigger(sta, ieee80211_get_tid(hdr)); + +out: + rcu_read_unlock(); +} + void rtw89_core_rx(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, struct sk_buff *skb) @@ -2722,6 +2820,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_rx_pkt_hdl(rtwdev, skb, desc_info); if (desc_info->long_rxdesc && BIT(desc_info->frame_type) & PPDU_FILTER_BITMAP) skb_queue_tail(&ppdu_sts->rx_queue[band], skb); @@ -3131,6 +3230,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1; struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; struct sk_buff *skb; @@ -3146,7 +3246,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, goto out; } - skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, qos); + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, qos); if (!skb) { ret = -ENOMEM; goto out; @@ -3367,21 +3467,10 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) return tfc_changed; } -static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) -{ - if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) - return; - - rtw89_enter_lps(rtwdev, rtwvif_link, true); -} - static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) { - struct rtw89_vif_link *rtwvif_link; + struct ieee80211_vif *vif; struct rtw89_vif *rtwvif; - unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) { if (rtwvif->tdls_peer) @@ -3393,8 +3482,13 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) continue; - rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) - rtw89_vif_enter_lps(rtwdev, rtwvif_link); + vif = rtwvif_to_vif(rtwvif); + + if (!(vif->type == NL80211_IFTYPE_STATION || + vif->type == NL80211_IFTYPE_P2P_CLIENT)) + continue; + + rtw89_enter_lps(rtwdev, rtwvif, true); } } @@ -3699,6 +3793,8 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, { const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + rtw89_assoc_link_clr(rtwsta_link); + if (vif->type == NL80211_IFTYPE_STATION) rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); @@ -3748,6 +3844,22 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, return ret; } +static bool rtw89_sta_link_can_er(struct rtw89_dev *rtwdev, + struct ieee80211_bss_conf *bss_conf, + struct ieee80211_link_sta *link_sta) +{ + if (!bss_conf->he_support || + bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE) + return false; + + if (rtwdev->chip->chip_id == RTL8852C && + rtw89_sta_link_has_su_mu_4xhe08(link_sta) && + !rtw89_sta_link_has_er_su_4xhe08(link_sta)) + return false; + + return true; +} + int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link) @@ -3758,12 +3870,11 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, rtwsta_link); const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + struct ieee80211_link_sta *link_sta; int ret; if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { if (sta->tdls) { - struct ieee80211_link_sta *link_sta; - rcu_read_lock(); link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); @@ -3814,9 +3925,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, rcu_read_lock(); bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); - if (bss_conf->he_support && - !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) - rtwsta_link->er_cap = true; + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + rtwsta_link->er_cap = rtw89_sta_link_can_er(rtwdev, bss_conf, link_sta); rcu_read_unlock(); @@ -3834,6 +3944,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); } + rtw89_assoc_link_set(rtwsta_link); return ret; } @@ -4433,6 +4544,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_phy_dm_init(rtwdev); rtw89_mac_cfg_ppdu_status_bands(rtwdev, true); + rtw89_mac_cfg_phy_rpt_bands(rtwdev, true); rtw89_mac_update_rts_threshold(rtwdev); rtw89_tas_reset(rtwdev); @@ -4755,6 +4867,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) rtw89_ser_init(rtwdev); rtw89_entity_init(rtwdev); rtw89_tas_init(rtwdev); + rtw89_phy_ant_gain_init(rtwdev); return 0; } @@ -5100,6 +5213,9 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) if (RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw)) ieee80211_hw_set(hw, CONNECTION_MONITOR); + if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) + ieee80211_hw_set(hw, AP_LINK_PS); + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 5ad32eacd0d5..155538370a89 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -830,6 +830,7 @@ enum rtw89_phy_idx { }; #define __RTW89_MLD_MAX_LINK_NUM 2 +#define RTW89_MLD_NON_STA_LINK_NUM 1 enum rtw89_chanctx_idx { RTW89_CHANCTX_0 = 0, @@ -1083,6 +1084,7 @@ struct rtw89_rx_desc_info { u16 offset; u16 rxd_len; bool ready; + u16 rssi; }; struct rtw89_rxdesc_short { @@ -1125,6 +1127,11 @@ struct rtw89_rxdesc_long_v2 { __le32 dword9; } __packed; +struct rtw89_rxdesc_phy_rpt_v2 { + __le32 dword0; + __le32 dword1; +} __packed; + struct rtw89_tx_desc_info { u16 pkt_size; u8 wp_offset; @@ -3358,6 +3365,8 @@ struct rtw89_sec_cam_entry { u8 spp_mode : 1; /* 256 bits */ u8 key[32]; + + struct ieee80211_key_conf *key_conf; }; struct rtw89_sta_link { @@ -3621,6 +3630,9 @@ struct rtw89_chip_ops { struct ieee80211_rx_status *status); void (*convert_rpl_to_rssi)(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); + void (*phy_rpt_to_rssi)(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status); void (*ctrl_nbtg_bt_tx)(struct rtw89_dev *rtwdev, bool en, enum rtw89_phy_idx phy_idx); void (*cfg_txrx_path)(struct rtw89_dev *rtwdev); @@ -4255,6 +4267,7 @@ struct rtw89_chip_info { u16 support_bandwidths; bool support_unii4; bool support_rnr; + bool support_ant_gain; bool ul_tb_waveform_ctrl; bool ul_tb_pwr_diff; bool hw_sec_hdr; @@ -4296,6 +4309,7 @@ struct rtw89_chip_info { const struct rtw89_rfe_parms *dflt_parms; const struct rtw89_chanctx_listener *chanctx_listener; + u8 txpwr_factor_bb; u8 txpwr_factor_rf; u8 txpwr_factor_mac; @@ -4448,8 +4462,12 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0, RTW89_FW_FEATURE_WOW_REASON_V1, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, RTW89_FW_FEATURE_RFK_RXDCK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, + RTW89_FW_FEATURE_NOTIFY_AP_INFO, + RTW89_FW_FEATURE_CH_INFO_BE_V0, + RTW89_FW_FEATURE_LPS_CH_INFO, }; struct rtw89_fw_suit { @@ -4597,6 +4615,44 @@ struct rtw89_sar_info { }; }; +enum rtw89_ant_gain_subband { + RTW89_ANT_GAIN_2GHZ_SUBBAND, + RTW89_ANT_GAIN_5GHZ_SUBBAND_1, /* U-NII-1 */ + RTW89_ANT_GAIN_5GHZ_SUBBAND_2, /* U-NII-2 */ + RTW89_ANT_GAIN_5GHZ_SUBBAND_2E, /* U-NII-2-Extended */ + RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4, /* U-NII-3 and U-NII-4 */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_6, /* U-NII-6 */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */ + RTW89_ANT_GAIN_6GHZ_SUBBAND_8, /* U-NII-8 */ + + RTW89_ANT_GAIN_SUBBAND_NR, +}; + +enum rtw89_ant_gain_domain_type { + RTW89_ANT_GAIN_ETSI = 0, + + RTW89_ANT_GAIN_DOMAIN_NUM, +}; + +#define RTW89_ANT_GAIN_CHAIN_NUM 2 +struct rtw89_ant_gain_info { + s8 offset[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR]; + u32 regd_enabled; +}; + +struct rtw89_6ghz_span { + enum rtw89_sar_subband sar_subband_low; + enum rtw89_sar_subband sar_subband_high; + enum rtw89_ant_gain_subband ant_gain_subband_low; + enum rtw89_ant_gain_subband ant_gain_subband_high; +}; + +#define RTW89_SAR_SPAN_VALID(span) ((span)->sar_subband_high) +#define RTW89_ANT_GAIN_SPAN_VALID(span) ((span)->ant_gain_subband_high) + enum rtw89_tas_state { RTW89_TAS_STATE_DPR_OFF, RTW89_TAS_STATE_DPR_ON, @@ -4781,6 +4837,7 @@ struct rtw89_pkt_drop_params { struct rtw89_pkt_stat { u16 beacon_nr; + u8 beacon_rate; u32 rx_rate_cnt[RTW89_HW_RATE_NR]; }; @@ -5556,6 +5613,9 @@ struct rtw89_dev { struct rtw89_rfe_data *rfe_data; enum rtw89_custid custid; + struct rtw89_sta_link __rcu *assoc_link_on_macid[RTW89_MAX_MAC_ID_NUM]; + refcount_t refcount_ap_info; + /* ensures exclusive access from mac80211 callbacks */ struct mutex mutex; struct list_head rtwvifs_list; @@ -5636,6 +5696,7 @@ struct rtw89_dev { struct rtw89_regulatory_info regulatory; struct rtw89_sar_info sar; struct rtw89_tas_info tas; + struct rtw89_ant_gain_info ant_gain; struct rtw89_btc btc; enum rtw89_ps_mode ps_mode; @@ -5654,10 +5715,17 @@ struct rtw89_dev { u8 priv[] __aligned(sizeof(void *)); }; +struct rtw89_link_conf_container { + struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; +}; + +#define RTW89_VIF_IDLE_LINK_ID 0 + struct rtw89_vif { struct rtw89_dev *rtwdev; struct list_head list; struct list_head mgnt_entry; + struct rtw89_link_conf_container __rcu *snap_link_confs; u8 mac_addr[ETH_ALEN]; __be32 ip_addr; @@ -5689,10 +5757,18 @@ static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id)) +enum rtw89_sta_flags { + RTW89_REMOTE_STA_IN_PS, + + NUM_OF_RTW89_STA_FLAGS, +}; + struct rtw89_sta { struct rtw89_dev *rtwdev; struct rtw89_vif *rtwvif; + DECLARE_BITMAP(flags, NUM_OF_RTW89_STA_FLAGS); + bool disassoc; struct sk_buff_head roc_queue; @@ -5700,6 +5776,8 @@ struct rtw89_sta { struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); + DECLARE_BITMAP(pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM); + u8 links_inst_valid_num; DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; @@ -5770,6 +5848,31 @@ u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link) return rtwsta_link - rtwsta->links_inst; } +static inline void rtw89_assoc_link_set(struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + + rcu_assign_pointer(rtwdev->assoc_link_on_macid[rtwsta_link->mac_id], + rtwsta_link); +} + +static inline void rtw89_assoc_link_clr(struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + + rcu_assign_pointer(rtwdev->assoc_link_on_macid[rtwsta_link->mac_id], + NULL); + synchronize_rcu(); +} + +static inline struct rtw89_sta_link * +rtw89_assoc_link_rcu_dereference(struct rtw89_dev *rtwdev, u8 macid) +{ + return rcu_dereference(rtwdev->assoc_link_on_macid[macid]); +} + static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { @@ -6194,9 +6297,19 @@ static inline struct ieee80211_bss_conf * __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct rtw89_link_conf_container *snap; struct ieee80211_bss_conf *bss_conf; + snap = rcu_dereference(rtwvif->snap_link_confs); + if (snap) { + bss_conf = snap->link_conf[rtwvif_link->link_id]; + goto out; + } + bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]); + +out: if (unlikely(!bss_conf)) { *nolink = true; return &vif->bss_conf; @@ -6605,6 +6718,16 @@ static inline void rtw89_chip_convert_rpl_to_rssi(struct rtw89_dev *rtwdev, chip->ops->convert_rpl_to_rssi(rtwdev, phy_ppdu); } +static inline void rtw89_chip_phy_rpt_to_rssi(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->phy_rpt_to_rssi) + chip->ops->phy_rpt_to_rssi(rtwdev, desc_info, rx_status); +} + static inline void rtw89_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en, enum rtw89_phy_idx phy_idx) { @@ -6753,6 +6876,26 @@ bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta) return false; } +static inline +bool rtw89_sta_link_has_su_mu_4xhe08(struct ieee80211_link_sta *link_sta) +{ + if (link_sta->he_cap.he_cap_elem.phy_cap_info[7] & + IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI) + return true; + + return false; +} + +static inline +bool rtw89_sta_link_has_er_su_4xhe08(struct ieee80211_link_sta *link_sta) +{ + if (link_sta->he_cap.he_cap_elem.phy_cap_info[8] & + IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI) + return true; + + return false; +} + static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) { @@ -6908,6 +7051,8 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); +const struct rtw89_6ghz_span * +rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, struct rtw89_chan *chan); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 6abd88fa80ba..fd86752d86f3 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -9,6 +9,7 @@ #include "fw.h" #include "mac.h" #include "pci.h" +#include "phy.h" #include "ps.h" #include "reg.h" #include "sar.h" @@ -882,6 +883,9 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v) seq_puts(m, "[TAS]\n"); rtw89_print_tas(m, rtwdev); + seq_puts(m, "[DAG]\n"); + rtw89_print_ant_gain(m, rtwdev, chan); + tbl = dbgfs_txpwr_tables[chip_gen]; if (!tbl) { ret = -EOPNOTSUPP; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 2191c037d72e..90db15685728 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -709,11 +709,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 7, BEACON_FILTER), __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER), __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, 27, 34, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD), @@ -727,7 +729,11 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 46, 0, NOTIFY_AP_INFO), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, @@ -2414,6 +2420,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, u8 *id) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1; struct rtw89_pktofld_info *info; struct sk_buff *skb; int ret; @@ -2430,10 +2437,10 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, skb = ieee80211_proberesp_get(rtwdev->hw, vif); break; case RTW89_PKT_OFLD_TYPE_NULL_DATA: - skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, false); + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, false); break; case RTW89_PKT_OFLD_TYPE_QOS_NULL: - skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, true); break; case RTW89_PKT_OFLD_TYPE_EAPOL_KEY: skb = rtw89_eapol_get(rtwdev, rtwvif_link); @@ -2589,14 +2596,17 @@ fail: return ret; } -int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif_link->chanctx_idx); const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_chan *chan; + struct rtw89_vif_link *rtwvif_link; struct rtw89_h2c_lps_ch_info *h2c; u32 len = sizeof(*h2c); + unsigned int link_id; struct sk_buff *skb; + bool no_chan = true; + u8 phy_idx; u32 done; int ret; @@ -2611,11 +2621,27 @@ int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt skb_put(skb, len); h2c = (struct rtw89_h2c_lps_ch_info *)skb->data; - h2c->info[0].central_ch = chan->channel; - h2c->info[0].pri_ch = chan->primary_channel; - h2c->info[0].band = chan->band_type; - h2c->info[0].bw = chan->band_width; - h2c->mlo_dbcc_mode_lps = cpu_to_le32(MLO_2_PLUS_0_1RF); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + phy_idx = rtwvif_link->phy_idx; + if (phy_idx >= ARRAY_SIZE(h2c->info)) + continue; + + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + no_chan = false; + + h2c->info[phy_idx].central_ch = chan->channel; + h2c->info[phy_idx].pri_ch = chan->primary_channel; + h2c->info[phy_idx].band = chan->band_type; + h2c->info[phy_idx].bw = chan->band_width; + } + + if (no_chan) { + rtw89_err(rtwdev, "no chan for h2c lps_ch_info\n"); + ret = -ENOENT; + goto fail; + } + + h2c->mlo_dbcc_mode_lps = cpu_to_le32(rtwdev->mlo_dbcc_mode); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM, @@ -2640,6 +2666,87 @@ fail: return ret; } +int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif) +{ + const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be; + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_lps_ml_cmn_info *h2c; + struct rtw89_vif_link *rtwvif_link; + const struct rtw89_chan *chan; + u8 bw_idx = RTW89_BB_BW_20_40; + u32 len = sizeof(*h2c); + unsigned int link_id; + struct sk_buff *skb; + u8 gain_band; + u32 done; + u8 path; + int ret; + int i; + + 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 lps_ml_cmn_info\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_lps_ml_cmn_info *)skb->data; + + h2c->fmt_id = 0x1; + + h2c->mlo_dbcc_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + path = rtwvif_link->phy_idx == RTW89_PHY_1 ? RF_PATH_B : RF_PATH_A; + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + gain_band = rtw89_subband_to_gain_band_be(chan->subband_type); + + h2c->central_ch[rtwvif_link->phy_idx] = chan->channel; + h2c->pri_ch[rtwvif_link->phy_idx] = chan->primary_channel; + h2c->band[rtwvif_link->phy_idx] = chan->band_type; + h2c->bw[rtwvif_link->phy_idx] = chan->band_width; + if (pkt_stat->beacon_rate < RTW89_HW_RATE_OFDM6) + h2c->bcn_rate_type[rtwvif_link->phy_idx] = 0x1; + else + h2c->bcn_rate_type[rtwvif_link->phy_idx] = 0x2; + + /* Fill BW20 RX gain table for beacon mode */ + for (i = 0; i < TIA_GAIN_NUM; i++) { + h2c->tia_gain[rtwvif_link->phy_idx][i] = + cpu_to_le16(gain->tia_gain[gain_band][bw_idx][path][i]); + } + memcpy(h2c->lna_gain[rtwvif_link->phy_idx], + gain->lna_gain[gain_band][bw_idx][path], + LNA_GAIN_NUM); + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM, + H2C_FUNC_FW_LPS_ML_CMN_INFO, 0, 0, len); + + rtw89_phy_write32_mask(rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT, 0); + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + ret = read_poll_timeout(rtw89_phy_read32_mask, done, done, 50, 5000, + true, rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT); + if (ret) + rtw89_warn(rtwdev, "h2c_lps_ml_cmn_info done polling timeout\n"); + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + #define H2C_P2P_ACT_LEN 20 int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, @@ -4954,13 +5061,14 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_h2c_chinfo_elem_be *elem; struct rtw89_mac_chinfo_be *ch_info; - struct rtw89_h2c_chinfo *h2c; + struct rtw89_h2c_chinfo_be *h2c; struct sk_buff *skb; unsigned int cond; + u8 ver = U8_MAX; int skb_len; int ret; - static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE); + static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE_BE); skb_len = struct_size(h2c, elem, ch_num); skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, skb_len); @@ -4969,8 +5077,11 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, return -ENOMEM; } + if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw)) + ver = 0; + skb_put(skb, sizeof(*h2c)); - h2c = (struct rtw89_h2c_chinfo *)skb->data; + h2c = (struct rtw89_h2c_chinfo_be *)skb->data; h2c->ch_num = ch_num; h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */ @@ -4980,8 +5091,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, list_for_each_entry(ch_info, chan_list, list) { elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, sizeof(*elem)); - elem->w0 = le32_encode_bits(ch_info->period, RTW89_H2C_CHINFO_BE_W0_PERIOD) | - le32_encode_bits(ch_info->dwell_time, RTW89_H2C_CHINFO_BE_W0_DWELL) | + elem->w0 = le32_encode_bits(ch_info->dwell_time, RTW89_H2C_CHINFO_BE_W0_DWELL) | le32_encode_bits(ch_info->central_ch, RTW89_H2C_CHINFO_BE_W0_CENTER_CH) | le32_encode_bits(ch_info->pri_ch, RTW89_H2C_CHINFO_BE_W0_PRI_CH); @@ -5028,6 +5138,12 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_SHORTSSIDS) | le32_encode_bits(ch_info->fw_probe0_bssids, RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_BSSIDS); + if (ver == 0) + elem->w0 |= + le32_encode_bits(ch_info->period, RTW89_H2C_CHINFO_BE_W0_PERIOD); + else + elem->w7 = le32_encode_bits(ch_info->period, + RTW89_H2C_CHINFO_BE_W7_PERIOD_V1); } rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -5171,6 +5287,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, u8 probe_id[NUM_NL80211_BANDS]; u8 cfg_len = sizeof(*h2c); unsigned int cond; + u8 ver = U8_MAX; void *ptr; int ret; u32 len; @@ -5191,6 +5308,9 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, memset(probe_id, RTW89_SCANOFLD_PKT_NONE, sizeof(probe_id)); + if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw)) + ver = 0; + if (!wowlan) { list_for_each_entry(pkt_info, &scan_info->pkt_list[NL80211_BAND_6GHZ], list) { if (pkt_info->wildcard_6ghz) { @@ -5286,9 +5406,7 @@ flex_member: le32_encode_bits(RTW89_OFF_CHAN_TIME / 10, RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY_VAL); - opch->w1 = le32_encode_bits(RTW89_CHANNEL_TIME, - RTW89_H2C_SCANOFLD_BE_OPCH_W1_DURATION) | - le32_encode_bits(op->band_type, + opch->w1 = le32_encode_bits(op->band_type, RTW89_H2C_SCANOFLD_BE_OPCH_W1_CH_BAND) | le32_encode_bits(op->band_width, RTW89_H2C_SCANOFLD_BE_OPCH_W1_BW) | @@ -5314,6 +5432,13 @@ flex_member: RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2) | le32_encode_bits(RTW89_SCANOFLD_PKT_NONE, RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT3); + + if (ver == 0) + opch->w1 |= le32_encode_bits(RTW89_CHANNEL_TIME, + RTW89_H2C_SCANOFLD_BE_OPCH_W1_DURATION); + else + opch->w4 = le32_encode_bits(RTW89_CHANNEL_TIME, + RTW89_H2C_SCANOFLD_BE_OPCH_W4_DURATION_V1); ptr += sizeof(*opch); } @@ -5416,7 +5541,9 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; + struct rtw89_fw_h2c_rfk_pre_info_common *common; struct rtw89_fw_h2c_rfk_pre_info_v0 *h2c_v0; + struct rtw89_fw_h2c_rfk_pre_info_v1 *h2c_v1; struct rtw89_fw_h2c_rfk_pre_info *h2c; u8 tbl_sel[NUM_OF_RTW89_FW_RFK_PATH]; u32 len = sizeof(*h2c); @@ -5426,7 +5553,10 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, u32 val32; int ret; - if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) { + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) { + len = sizeof(*h2c_v1); + ver = 1; + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) { len = sizeof(*h2c_v0); ver = 0; } @@ -5438,17 +5568,18 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, } skb_put(skb, len); h2c = (struct rtw89_fw_h2c_rfk_pre_info *)skb->data; + common = &h2c->base_v1.common; - h2c->common.mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + common->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR); BUILD_BUG_ON(ARRAY_SIZE(rfk_mcc->data) < NUM_OF_RTW89_FW_RFK_PATH); for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) { for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { - h2c->common.dbcc.ch[path][tbl] = + common->dbcc.ch[path][tbl] = cpu_to_le32(rfk_mcc->data[path].ch[tbl]); - h2c->common.dbcc.band[path][tbl] = + common->dbcc.band[path][tbl] = cpu_to_le32(rfk_mcc->data[path].band[tbl]); } } @@ -5456,13 +5587,19 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { tbl_sel[path] = rfk_mcc->data[path].table_idx; - h2c->common.tbl.cur_ch[path] = + common->tbl.cur_ch[path] = cpu_to_le32(rfk_mcc->data[path].ch[tbl_sel[path]]); - h2c->common.tbl.cur_band[path] = + common->tbl.cur_band[path] = cpu_to_le32(rfk_mcc->data[path].band[tbl_sel[path]]); + + if (ver <= 1) + continue; + + h2c->cur_bandwidth[path] = + cpu_to_le32(rfk_mcc->data[path].bw[tbl_sel[path]]); } - h2c->common.phy_idx = cpu_to_le32(phy_idx); + common->phy_idx = cpu_to_le32(phy_idx); if (ver == 0) { /* RFK_PRE_NOTIFY_V0 */ h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_v0 *)skb->data; @@ -5488,8 +5625,10 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, goto done; } - if (rtw89_is_mlo_1_1(rtwdev)) - h2c->mlo_1_1 = cpu_to_le32(1); + if (rtw89_is_mlo_1_1(rtwdev)) { + h2c_v1 = &h2c->base_v1; + h2c_v1->mlo_1_1 = cpu_to_le32(1); + } done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, @@ -6496,7 +6635,7 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&chan_list); for (idx = 0, list_len = 0; - idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT; + idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_AX; idx++, list_len++) { channel = nd_config->channels[idx]; ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); @@ -6547,7 +6686,7 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&chan_list); for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0; - idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT; + idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_AX; idx++, list_len++) { channel = req->channels[idx]; ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); @@ -6624,7 +6763,7 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&chan_list); for (idx = 0, list_len = 0; - idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT; + idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_BE; idx++, list_len++) { channel = nd_config->channels[idx]; ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); @@ -6679,7 +6818,7 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&chan_list); for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0; - idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT; + idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_BE; idx++, list_len++) { channel = req->channels[idx]; ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); @@ -8164,6 +8303,71 @@ int rtw89_fw_h2c_mrc_upd_duration(struct rtw89_dev *rtwdev, return 0; } +static int rtw89_fw_h2c_ap_info(struct rtw89_dev *rtwdev, bool en) +{ + struct rtw89_h2c_ap_info *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 ap info\n"); + return -ENOMEM; + } + + skb_put(skb, len); + h2c = (struct rtw89_h2c_ap_info *)skb->data; + + h2c->w0 = le32_encode_bits(en, RTW89_H2C_AP_INFO_W0_PWR_INT_EN); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_AP, + H2C_FUNC_AP_INFO, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + dev_kfree_skb_any(skb); + return -EBUSY; + } + + return 0; +} + +int rtw89_fw_h2c_ap_info_refcount(struct rtw89_dev *rtwdev, bool en) +{ + int ret; + + if (en) { + if (refcount_inc_not_zero(&rtwdev->refcount_ap_info)) + return 0; + } else { + if (!refcount_dec_and_test(&rtwdev->refcount_ap_info)) + return 0; + } + + ret = rtw89_fw_h2c_ap_info(rtwdev, en); + if (ret) { + if (!test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) + return ret; + + /* During recovery, neither driver nor stack has full error + * handling, so show a warning, but return 0 with refcount + * increased normally. It can avoid underflow when calling + * with @en == false later. + */ + rtw89_warn(rtwdev, "h2c ap_info failed during SER\n"); + } + + if (en) + refcount_set(&rtwdev->refcount_ap_info, 1); + + return 0; +} + static bool __fw_txpwr_entry_zero_ext(const void *ext_ptr, u8 ext_len) { static const u8 zeros[U8_MAX] = {}; diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index efa63d444821..a3fe183c2ab0 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -310,9 +310,12 @@ struct rtw89_fw_macid_pause_sleep_grp { #define RTW89_SCANOFLD_DEBUG_MASK 0x1F #define RTW89_CHAN_INVALID 0xFF #define RTW89_MAC_CHINFO_SIZE 28 +#define RTW89_MAC_CHINFO_SIZE_BE 32 #define RTW89_SCAN_LIST_GUARD 4 -#define RTW89_SCAN_LIST_LIMIT \ - ((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD) +#define RTW89_SCAN_LIST_LIMIT(size) \ + ((RTW89_H2C_MAX_SIZE / (size)) - RTW89_SCAN_LIST_GUARD) +#define RTW89_SCAN_LIST_LIMIT_AX RTW89_SCAN_LIST_LIMIT(RTW89_MAC_CHINFO_SIZE) +#define RTW89_SCAN_LIST_LIMIT_BE RTW89_SCAN_LIST_LIMIT(RTW89_MAC_CHINFO_SIZE_BE) #define RTW89_BCN_LOSS_CNT 10 @@ -1780,6 +1783,21 @@ struct rtw89_h2c_lps_ch_info { __le32 mlo_dbcc_mode_lps; } __packed; +struct rtw89_h2c_lps_ml_cmn_info { + u8 fmt_id; + u8 rsvd0[3]; + __le32 mlo_dbcc_mode; + u8 central_ch[RTW89_PHY_MAX]; + u8 pri_ch[RTW89_PHY_MAX]; + u8 bw[RTW89_PHY_MAX]; + u8 band[RTW89_PHY_MAX]; + u8 bcn_rate_type[RTW89_PHY_MAX]; + u8 rsvd1[2]; + __le16 tia_gain[RTW89_PHY_MAX][TIA_GAIN_NUM]; + u8 lna_gain[RTW89_PHY_MAX][LNA_GAIN_NUM]; + u8 rsvd2[2]; +} __packed; + static inline void RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(void *cmd, u32 val) { le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 0)); @@ -2647,6 +2665,7 @@ struct rtw89_h2c_chinfo_elem_be { __le32 w4; __le32 w5; __le32 w6; + __le32 w7; } __packed; #define RTW89_H2C_CHINFO_BE_W0_PERIOD GENMASK(7, 0) @@ -2678,6 +2697,7 @@ struct rtw89_h2c_chinfo_elem_be { #define RTW89_H2C_CHINFO_BE_W5_FW_PROBE0_SSIDS GENMASK(31, 16) #define RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_SHORTSSIDS GENMASK(15, 0) #define RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_BSSIDS GENMASK(31, 16) +#define RTW89_H2C_CHINFO_BE_W7_PERIOD_V1 GENMASK(15, 0) struct rtw89_h2c_chinfo { u8 ch_num; @@ -2687,6 +2707,14 @@ struct rtw89_h2c_chinfo { struct rtw89_h2c_chinfo_elem elem[] __counted_by(ch_num); } __packed; +struct rtw89_h2c_chinfo_be { + u8 ch_num; + u8 elem_size; + u8 arg; + u8 rsvd0; + struct rtw89_h2c_chinfo_elem_be elem[] __counted_by(ch_num); +} __packed; + #define RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK BIT(0) #define RTW89_H2C_CHINFO_ARG_APPEND_MASK BIT(1) @@ -2733,6 +2761,7 @@ struct rtw89_h2c_scanofld_be_opch { __le32 w1; __le32 w2; __le32 w3; + __le32 w4; } __packed; #define RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID GENMASK(15, 0) @@ -2754,6 +2783,7 @@ struct rtw89_h2c_scanofld_be_opch { #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT1 GENMASK(15, 8) #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2 GENMASK(23, 16) #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT3 GENMASK(31, 24) +#define RTW89_H2C_SCANOFLD_BE_OPCH_W4_DURATION_V1 GENMASK(15, 0) struct rtw89_h2c_scanofld_be { __le32 w0; @@ -3466,6 +3496,12 @@ struct rtw89_h2c_wow_aoac { __le32 w0; } __packed; +struct rtw89_h2c_ap_info { + __le32 w0; +} __packed; + +#define RTW89_H2C_AP_INFO_W0_PWR_INT_EN BIT(0) + #define RTW89_C2H_HEADER_LEN 8 struct rtw89_c2h_hdr { @@ -3590,6 +3626,7 @@ struct rtw89_c2h_scanofld { __le32 w5; __le32 w6; __le32 w7; + __le32 w8; } __packed; #define RTW89_C2H_SCANOFLD_W2_PRI_CH GENMASK(7, 0) @@ -3604,6 +3641,8 @@ struct rtw89_c2h_scanofld { #define RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD GENMASK(15, 8) #define RTW89_C2H_SCANOFLD_W6_FW_DEF GENMASK(23, 16) #define RTW89_C2H_SCANOFLD_W7_REPORT_TSF GENMASK(31, 0) +#define RTW89_C2H_SCANOFLD_W8_PERIOD_V1 GENMASK(15, 0) +#define RTW89_C2H_SCANOFLD_W8_EXPECT_PERIOD_V1 GENMASK(31, 16) #define RTW89_GET_MAC_C2H_MCC_RCV_ACK_GROUP(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0)) @@ -3725,6 +3764,14 @@ struct rtw89_c2h_wow_aoac_report { #define RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX BIT(0) +struct rtw89_c2h_pwr_int_notify { + struct rtw89_c2h_hdr hdr; + __le32 w2; +} __packed; + +#define RTW89_C2H_PWR_INT_NOTIFY_W2_MACID GENMASK(15, 0) +#define RTW89_C2H_PWR_INT_NOTIFY_W2_PWR_STATUS BIT(16) + struct rtw89_h2c_tx_duty { __le32 w0; __le32 w1; @@ -4168,6 +4215,10 @@ enum rtw89_mrc_h2c_func { #define RTW89_MRC_WAIT_COND_REQ_TSF \ RTW89_MRC_WAIT_COND(0 /* don't care */, H2C_FUNC_MRC_REQ_TSF) +/* CLASS 36 - AP */ +#define H2C_CL_AP 0x24 +#define H2C_FUNC_AP_INFO 0x0 + #define H2C_CAT_OUTSRC 0x2 #define H2C_CL_OUTSRC_RA 0x1 @@ -4175,6 +4226,7 @@ enum rtw89_mrc_h2c_func { #define H2C_CL_OUTSRC_DM 0x2 #define H2C_FUNC_FW_LPS_CH_INFO 0xb +#define H2C_FUNC_FW_LPS_ML_CMN_INFO 0xe #define H2C_CL_OUTSRC_RF_REG_A 0x8 #define H2C_CL_OUTSRC_RF_REG_B 0x9 @@ -4241,11 +4293,16 @@ struct rtw89_fw_h2c_rfk_pre_info_v0 { } __packed mlo; } __packed; -struct rtw89_fw_h2c_rfk_pre_info { +struct rtw89_fw_h2c_rfk_pre_info_v1 { struct rtw89_fw_h2c_rfk_pre_info_common common; __le32 mlo_1_1; } __packed; +struct rtw89_fw_h2c_rfk_pre_info { + struct rtw89_fw_h2c_rfk_pre_info_v1 base_v1; + __le32 cur_bandwidth[NUM_OF_RTW89_FW_RFK_PATH]; +} __packed; + struct rtw89_h2c_rf_tssi { __le16 len; u8 phy; @@ -4602,8 +4659,9 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, struct rtw89_lps_parm *lps_param); -int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link); +int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif); int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len); @@ -4697,6 +4755,7 @@ int rtw89_fw_h2c_mrc_sync(struct rtw89_dev *rtwdev, const struct rtw89_fw_mrc_sync_arg *arg); int rtw89_fw_h2c_mrc_upd_duration(struct rtw89_dev *rtwdev, const struct rtw89_fw_mrc_upd_duration_arg *arg); +int rtw89_fw_h2c_ap_info_refcount(struct rtw89_dev *rtwdev, bool en); static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) { diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 7907b84d204b..c78066fd4504 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4788,9 +4788,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; struct rtw89_vif *rtwvif; struct rtw89_chan new; - u8 reason, status, tx_fail, band, actual_period, expect_period; u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf; + u16 actual_period, expect_period; + u8 reason, status, tx_fail, band; u8 mac_idx, sw_def, fw_def; + u8 ver = U8_MAX; u16 chan; int ret; @@ -4799,6 +4801,9 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, rtwvif = rtwvif_link->rtwvif; + if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw)) + ver = 0; + tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL); status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS); chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH); @@ -4811,21 +4816,28 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (!(rtwdev->chip->support_bands & BIT(NL80211_BAND_6GHZ))) band = chan > 14 ? RTW89_BAND_5G : RTW89_BAND_2G; - rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, - "mac_idx[%d] band: %d, chan: %d, reason: %d, status: %d, tx_fail: %d, actual: %d\n", - mac_idx, band, chan, reason, status, tx_fail, actual_period); - if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) { sw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_SW_DEF); - expect_period = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD); fw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_FW_DEF); report_tsf = le32_get_bits(c2h->w7, RTW89_C2H_SCANOFLD_W7_REPORT_TSF); + if (ver == 0) { + expect_period = + le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD); + } else { + actual_period = le32_get_bits(c2h->w8, RTW89_C2H_SCANOFLD_W8_PERIOD_V1); + expect_period = + le32_get_bits(c2h->w8, RTW89_C2H_SCANOFLD_W8_EXPECT_PERIOD_V1); + } rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, "sw_def: %d, fw_def: %d, tsf: %x, expect: %d\n", sw_def, fw_def, report_tsf, expect_period); } + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "mac_idx[%d] band: %d, chan: %d, reason: %d, status: %d, tx_fail: %d, actual: %d\n", + mac_idx, band, chan, reason, status, tx_fail, actual_period); + switch (reason) { case RTW89_SCAN_LEAVE_OP_NOTIFY: case RTW89_SCAN_LEAVE_CH_NOTIFY: @@ -5364,6 +5376,39 @@ rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 rtw89_complete_cond(wait, cond, &data); } +static void +rtw89_mac_c2h_pwr_int_notify(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len) +{ + const struct rtw89_c2h_pwr_int_notify *c2h; + struct rtw89_sta_link *rtwsta_link; + struct ieee80211_sta *sta; + struct rtw89_sta *rtwsta; + u16 macid; + bool ps; + + c2h = (const struct rtw89_c2h_pwr_int_notify *)skb->data; + macid = le32_get_bits(c2h->w2, RTW89_C2H_PWR_INT_NOTIFY_W2_MACID); + ps = le32_get_bits(c2h->w2, RTW89_C2H_PWR_INT_NOTIFY_W2_PWR_STATUS); + + rcu_read_lock(); + + rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, macid); + if (unlikely(!rtwsta_link)) + goto out; + + rtwsta = rtwsta_link->rtwsta; + if (ps) + set_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags); + else + clear_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags); + + sta = rtwsta_to_sta(rtwsta); + ieee80211_sta_ps_transition(sta, ps); + +out: + rcu_read_unlock(); +} + static void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { @@ -5409,6 +5454,12 @@ void (* const rtw89_mac_c2h_wow_handler[])(struct rtw89_dev *rtwdev, [RTW89_MAC_C2H_FUNC_AOAC_REPORT] = rtw89_mac_c2h_wow_aoac_rpt, }; +static +void (* const rtw89_mac_c2h_ap_handler[])(struct rtw89_dev *rtwdev, + struct sk_buff *c2h, u32 len) = { + [RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY] = rtw89_mac_c2h_pwr_int_notify, +}; + static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev, struct sk_buff *skb) { @@ -5463,6 +5514,13 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h, return true; case RTW89_MAC_C2H_CLASS_WOW: return true; + case RTW89_MAC_C2H_CLASS_AP: + switch (func) { + default: + return false; + case RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY: + return true; + } } } @@ -5493,14 +5551,18 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (func < NUM_OF_RTW89_MAC_C2H_FUNC_WOW) handler = rtw89_mac_c2h_wow_handler[func]; break; + case RTW89_MAC_C2H_CLASS_AP: + if (func < NUM_OF_RTW89_MAC_C2H_FUNC_AP) + handler = rtw89_mac_c2h_ap_handler[func]; + break; case RTW89_MAC_C2H_CLASS_FWDBG: return; default: - rtw89_info(rtwdev, "c2h class %d not support\n", class); + rtw89_info(rtwdev, "MAC c2h class %d not support\n", class); return; } if (!handler) { - rtw89_info(rtwdev, "c2h class %d func %d not support\n", class, + rtw89_info(rtwdev, "MAC c2h class %d func %d not support\n", class, func); return; } @@ -6674,6 +6736,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .typ_fltr_opt = rtw89_mac_typ_fltr_opt_ax, .cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax, + .cfg_phy_rpt = NULL, .dle_mix_cfg = dle_mix_cfg_ax, .chk_dle_rdy = chk_dle_rdy_ax, diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 18579c020548..8edea96d037f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -169,6 +169,20 @@ enum rtw89_mac_ax_l0_to_l1_event { MAC_AX_L0_TO_L1_EVENT_MAX = 15, }; +enum rtw89_mac_phy_rpt_size { + MAC_AX_PHY_RPT_SIZE_0 = 0, + MAC_AX_PHY_RPT_SIZE_8 = 1, + MAC_AX_PHY_RPT_SIZE_16 = 2, + MAC_AX_PHY_RPT_SIZE_24 = 3, +}; + +enum rtw89_mac_hdr_cnv_size { + MAC_AX_HDR_CNV_SIZE_0 = 0, + MAC_AX_HDR_CNV_SIZE_32 = 1, + MAC_AX_HDR_CNV_SIZE_64 = 2, + MAC_AX_HDR_CNV_SIZE_96 = 3, +}; + enum rtw89_mac_wow_fw_status { WOWLAN_NOT_READY = 0x00, WOWLAN_SLEEP_READY = 0x01, @@ -426,6 +440,12 @@ enum rtw89_mac_c2h_wow_func { NUM_OF_RTW89_MAC_C2H_FUNC_WOW, }; +enum rtw89_mac_c2h_ap_func { + RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY = 0, + + NUM_OF_RTW89_MAC_C2H_FUNC_AP, +}; + enum rtw89_mac_c2h_class { RTW89_MAC_C2H_CLASS_INFO = 0x0, RTW89_MAC_C2H_CLASS_OFLD = 0x1, @@ -434,6 +454,7 @@ enum rtw89_mac_c2h_class { RTW89_MAC_C2H_CLASS_MCC = 0x4, RTW89_MAC_C2H_CLASS_FWDBG = 0x5, RTW89_MAC_C2H_CLASS_MRC = 0xe, + RTW89_MAC_C2H_CLASS_AP = 0x18, RTW89_MAC_C2H_CLASS_MAX, }; @@ -961,6 +982,7 @@ struct rtw89_mac_gen_def { enum rtw89_mac_fwd_target fwd_target, u8 mac_idx); int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable); + void (*cfg_phy_rpt)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable); int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg); int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple); @@ -1216,6 +1238,27 @@ int rtw89_mac_stop_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); int rtw89_mac_resume_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); +void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable); + +static inline +void rtw89_mac_cfg_phy_rpt(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (mac->cfg_phy_rpt) + mac->cfg_phy_rpt(rtwdev, mac_idx, enable); +} + +static inline +void rtw89_mac_cfg_phy_rpt_bands(struct rtw89_dev *rtwdev, bool enable) +{ + rtw89_mac_cfg_phy_rpt(rtwdev, RTW89_MAC_0, enable); + + if (!rtwdev->dbcc_en) + return; + + rtw89_mac_cfg_phy_rpt(rtwdev, RTW89_MAC_1, enable); +} static inline int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 619d2d3771d5..5eac0b524060 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -202,7 +202,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); - rtwvif_link = rtw89_vif_set_link(rtwvif, 0); + rtwvif_link = rtw89_vif_set_link(rtwvif, RTW89_VIF_IDLE_LINK_ID); if (!rtwvif_link) { ret = -EINVAL; goto release_port; @@ -218,7 +218,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, return 0; unset_link: - rtw89_vif_unset_link(rtwvif, 0); + rtw89_vif_unset_link(rtwvif, RTW89_VIF_IDLE_LINK_ID); release_port: list_del_init(&rtwvif->list); rtw89_core_release_bit_map(rtwdev->hw_port, port); @@ -246,17 +246,17 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, mutex_lock(&rtwdev->mutex); - rtwvif_link = rtwvif->links[0]; + rtwvif_link = rtwvif->links[RTW89_VIF_IDLE_LINK_ID]; if (unlikely(!rtwvif_link)) { rtw89_err(rtwdev, "%s: rtwvif link (link_id %u) is not active\n", - __func__, 0); + __func__, RTW89_VIF_IDLE_LINK_ID); goto bottom; } __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); - rtw89_vif_unset_link(rtwvif, 0); + rtw89_vif_unset_link(rtwvif, RTW89_VIF_IDLE_LINK_ID); bottom: list_del_init(&rtwvif->list); @@ -509,6 +509,7 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, rtw89_core_txq_init(rtwdev, sta->txq[i]); skb_queue_head_init(&rtwsta->roc_queue); + bitmap_zero(rtwsta->pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM); rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id); if (!rtwsta_link) { @@ -775,6 +776,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_vif_link *rtwvif_link; const struct rtw89_chan *chan; + int ret = 0; mutex_lock(&rtwdev->mutex); @@ -783,6 +785,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, rtw89_err(rtwdev, "%s: rtwvif link (link_id %u) is not active\n", __func__, link_conf->link_id); + ret = -ENOLINK; goto out; } @@ -804,12 +807,18 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) { + ret = rtw89_fw_h2c_ap_info_refcount(rtwdev, true); + if (ret) + goto out; + } + rtw89_queue_chanctx_work(rtwdev); out: mutex_unlock(&rtwdev->mutex); - return 0; + return ret; } static @@ -830,6 +839,9 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } + if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) + rtw89_fw_h2c_ap_info_refcount(rtwdev, false); + rtw89_mac_stop_ap(rtwdev, rtwvif_link); rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); @@ -1295,10 +1307,15 @@ static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_link_sta *link_sta, u32 changed) { - struct ieee80211_sta *sta = link_sta->sta; + struct rtw89_sta *rtwsta = sta_to_rtwsta(link_sta->sta); struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_sta_link *rtwsta_link; - rtw89_phy_ra_update_sta(rtwdev, sta, changed); + rtwsta_link = rtwsta->links[link_sta->link_id]; + if (unlikely(!rtwsta_link)) + return; + + rtw89_phy_ra_update_sta_link(rtwdev, rtwsta_link, changed); } static int rtw89_ops_add_chanctx(struct ieee80211_hw *hw, @@ -1473,6 +1490,259 @@ static int rtw89_ops_set_tid_config(struct ieee80211_hw *hw, return 0; } +static bool rtw89_can_work_on_links(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, u16 links) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + u8 w = hweight16(links); + + if (vif->type != NL80211_IFTYPE_STATION && + w > RTW89_MLD_NON_STA_LINK_NUM) + return false; + + return w <= rtwvif->links_inst_valid_num; +} + +static bool rtw89_ops_can_activate_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 active_links) +{ + struct rtw89_dev *rtwdev = hw->priv; + + guard(mutex)(&rtwdev->mutex); + + return rtw89_can_work_on_links(rtwdev, vif, active_links); +} + +static void __rtw89_ops_clr_vif_links(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + unsigned long clr_links) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + for_each_set_bit(link_id, &clr_links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwvif_link = rtwvif->links[link_id]; + if (unlikely(!rtwvif_link)) + continue; + + __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); + + rtw89_vif_unset_link(rtwvif, link_id); + } +} + +static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + unsigned long set_links) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + int ret; + + for_each_set_bit(link_id, &set_links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwvif_link = rtw89_vif_set_link(rtwvif, link_id); + if (!rtwvif_link) + return -EINVAL; + + ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link); + if (ret) { + rtw89_err(rtwdev, "%s: failed to add iface (link id %u)\n", + __func__, link_id); + return ret; + } + } + + return 0; +} + +static +int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 old_links, u16 new_links, + struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) +{ + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + unsigned long clr_links = old_links & ~new_links; + unsigned long set_links = new_links & ~old_links; + bool removing_links = !old_links || clr_links; + struct rtw89_link_conf_container *snap; + int ret = 0; + int i; + + guard(mutex)(&rtwdev->mutex); + + rtw89_debug(rtwdev, RTW89_DBG_STATE, + "%s: old_links (0x%08x) -> new_links (0x%08x)\n", + __func__, old_links, new_links); + + if (!rtw89_can_work_on_links(rtwdev, vif, new_links)) + return -EOPNOTSUPP; + + if (removing_links) { + snap = kzalloc(sizeof(*snap), GFP_KERNEL); + if (!snap) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(snap->link_conf); i++) + snap->link_conf[i] = old[i]; + + rcu_assign_pointer(rtwvif->snap_link_confs, snap); + } + + /* might depend on @snap; don't change order */ + rtw89_leave_ips_by_hwflags(rtwdev); + + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + + if (!old_links) + __rtw89_ops_clr_vif_links(rtwdev, rtwvif, + BIT(RTW89_VIF_IDLE_LINK_ID)); + else if (clr_links) + __rtw89_ops_clr_vif_links(rtwdev, rtwvif, clr_links); + + if (removing_links) { + /* @snap is required if and only if during removing links. + * However, it's done here. So, cleanup @snap immediately. + */ + rcu_assign_pointer(rtwvif->snap_link_confs, NULL); + + /* The pointers in @old will free after this function return, + * so synchronously wait for all readers of snap to be done. + */ + synchronize_rcu(); + kfree(snap); + } + + if (set_links) { + ret = __rtw89_ops_set_vif_links(rtwdev, rtwvif, set_links); + if (ret) + __rtw89_ops_clr_vif_links(rtwdev, rtwvif, set_links); + } else if (!new_links) { + ret = __rtw89_ops_set_vif_links(rtwdev, rtwvif, + BIT(RTW89_VIF_IDLE_LINK_ID)); + if (ret) + __rtw89_ops_clr_vif_links(rtwdev, rtwvif, + BIT(RTW89_VIF_IDLE_LINK_ID)); + } + + rtw89_enter_ips_by_hwflags(rtwdev); + return ret; +} + +static void __rtw89_ops_clr_sta_links(struct rtw89_dev *rtwdev, + struct rtw89_sta *rtwsta, + unsigned long clr_links) +{ + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + for_each_set_bit(link_id, &clr_links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwsta_link = rtwsta->links[link_id]; + if (unlikely(!rtwsta_link)) + continue; + + rtwvif_link = rtwsta_link->rtwvif_link; + + rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); + rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); + rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); + + rtw89_sta_unset_link(rtwsta, link_id); + } +} + +static int __rtw89_ops_set_sta_links(struct rtw89_dev *rtwdev, + struct rtw89_sta *rtwsta, + unsigned long set_links) +{ + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + u8 sec_cam_idx; + int ret; + + for_each_set_bit(link_id, &set_links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwsta_link = rtw89_sta_set_link(rtwsta, link_id); + if (!rtwsta_link) + return -EINVAL; + + rtwvif_link = rtwsta_link->rtwvif_link; + + ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_err(rtwdev, "%s: failed to add sta (link id %u)\n", + __func__, link_id); + return ret; + } + + rtw89_vif_type_mapping(rtwvif_link, true); + + ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_err(rtwdev, "%s: failed to assoc sta (link id %u)\n", + __func__, link_id); + return ret; + } + + __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); + + for_each_set_bit(sec_cam_idx, rtwsta->pairwise_sec_cam_map, + RTW89_MAX_SEC_CAM_NUM) { + ret = rtw89_cam_attach_link_sec_cam(rtwdev, + rtwvif_link, + rtwsta_link, + sec_cam_idx); + if (ret) { + rtw89_err(rtwdev, + "%s: failed to apply pairwise key (link id %u)\n", + __func__, link_id); + return ret; + } + } + } + + return 0; +} + +static +int rtw89_ops_change_sta_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u16 old_links, u16 new_links) +{ + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + unsigned long clr_links = old_links & ~new_links; + unsigned long set_links = new_links & ~old_links; + int ret = 0; + + guard(mutex)(&rtwdev->mutex); + + rtw89_debug(rtwdev, RTW89_DBG_STATE, + "%s: old_links (0x%08x) -> new_links (0x%08x)\n", + __func__, old_links, new_links); + + if (!rtw89_can_work_on_links(rtwdev, vif, new_links)) + return -EOPNOTSUPP; + + rtw89_leave_ps_mode(rtwdev); + + if (clr_links) + __rtw89_ops_clr_sta_links(rtwdev, rtwsta, clr_links); + + if (set_links) { + ret = __rtw89_ops_set_sta_links(rtwdev, rtwsta, set_links); + if (ret) + __rtw89_ops_clr_sta_links(rtwdev, rtwsta, set_links); + } + + return ret; +} + #ifdef CONFIG_PM static int rtw89_ops_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) @@ -1600,6 +1870,9 @@ const struct ieee80211_ops rtw89_ops = { .set_sar_specs = rtw89_ops_set_sar_specs, .link_sta_rc_update = rtw89_ops_sta_rc_update, .set_tid_config = rtw89_ops_set_tid_config, + .can_activate_links = rtw89_ops_can_activate_links, + .change_vif_links = rtw89_ops_change_vif_links, + .change_sta_links = rtw89_ops_change_sta_links, #ifdef CONFIG_PM .suspend = rtw89_ops_suspend, .resume = rtw89_ops_resume, diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index f7a396c8a3cd..2dbdeae904ad 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -1988,6 +1988,20 @@ int rtw89_mac_resume_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en) } EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v2); +void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) +{ + u32 reg, val; + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RCR, mac_idx); + val = enable ? MAC_AX_PHY_RPT_SIZE_8 : MAC_AX_PHY_RPT_SIZE_0; + rtw89_write32_mask(rtwdev, reg, B_BE_PHY_RPT_SZ_MASK, val); + rtw89_write32_mask(rtwdev, reg, B_BE_HDR_CNV_SZ_MASK, MAC_AX_HDR_CNV_SIZE_0); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_DRV_INFO_OPTION, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_BE_DRV_INFO_PHYRPT_EN, enable); +} +EXPORT_SYMBOL(rtw89_mac_cfg_phy_rpt_be); + static int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) { @@ -2583,6 +2597,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .typ_fltr_opt = rtw89_mac_typ_fltr_opt_be, .cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_be, + .cfg_phy_rpt = rtw89_mac_cfg_phy_rpt_be, .dle_mix_cfg = dle_mix_cfg_be, .chk_dle_rdy = chk_dle_rdy_be, diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index f923bec03d41..c3a027735d0f 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -2516,7 +2516,7 @@ static int rtw89_pci_dphy_delay(struct rtw89_dev *rtwdev) PCIE_DPHY_DLY_25US, PCIE_PHY_GEN1); } -static void rtw89_pci_power_wake(struct rtw89_dev *rtwdev, bool pwr_up) +static void rtw89_pci_power_wake_ax(struct rtw89_dev *rtwdev, bool pwr_up) { if (pwr_up) rtw89_write32_set(rtwdev, R_AX_HCI_OPT_CTRL, BIT_WAKE_CTRL); @@ -2825,6 +2825,8 @@ static int rtw89_pci_ops_deinit(struct rtw89_dev *rtwdev) { const struct rtw89_pci_info *info = rtwdev->pci_info; + rtw89_pci_power_wake(rtwdev, false); + if (rtwdev->chip->chip_id == RTL8852A) { /* ltr sw trigger */ rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_APP_LTR_IDLE); @@ -2867,7 +2869,7 @@ static int rtw89_pci_ops_mac_pre_init_ax(struct rtw89_dev *rtwdev) return ret; } - rtw89_pci_power_wake(rtwdev, true); + rtw89_pci_power_wake_ax(rtwdev, true); rtw89_pci_autoload_hang(rtwdev); rtw89_pci_l12_vmain(rtwdev); rtw89_pci_gen2_force_ib(rtwdev); @@ -2912,6 +2914,13 @@ static int rtw89_pci_ops_mac_pre_init_ax(struct rtw89_dev *rtwdev) return 0; } +static int rtw89_pci_ops_mac_pre_deinit_ax(struct rtw89_dev *rtwdev) +{ + rtw89_pci_power_wake_ax(rtwdev, false); + + return 0; +} + int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en) { u32 val; @@ -4325,7 +4334,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { B_AX_RDU_INT}, .mac_pre_init = rtw89_pci_ops_mac_pre_init_ax, - .mac_pre_deinit = NULL, + .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit_ax, .mac_post_init = rtw89_pci_ops_mac_post_init_ax, .clr_idx_all = rtw89_pci_clr_idx_all_ax, @@ -4343,6 +4352,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { .l1ss_set = rtw89_pci_l1ss_set_ax, .disable_eq = rtw89_pci_disable_eq_ax, + .power_wake = rtw89_pci_power_wake_ax, }; EXPORT_SYMBOL(rtw89_pci_gen_ax); diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index b68e2d82eea9..d52db4ca1b99 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -1290,6 +1290,7 @@ struct rtw89_pci_gen_def { void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable); void (*disable_eq)(struct rtw89_dev *rtwdev); + void (*power_wake)(struct rtw89_dev *rtwdev, bool pwr_up); }; #define RTW89_PCI_SSID(v, d, ssv, ssd, cust) \ @@ -1805,4 +1806,12 @@ static inline void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) gen_def->disable_eq(rtwdev); } +static inline void rtw89_pci_power_wake(struct rtw89_dev *rtwdev, bool pwr_up) +{ + const struct rtw89_pci_info *info = rtwdev->pci_info; + const struct rtw89_pci_gen_def *gen_def = info->gen_def; + + gen_def->power_wake(rtwdev, pwr_up); +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c index 34154506f5d4..cd39eebe8186 100644 --- a/drivers/net/wireless/realtek/rtw89/pci_be.c +++ b/drivers/net/wireless/realtek/rtw89/pci_be.c @@ -691,5 +691,6 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_be = { .l1ss_set = rtw89_pci_l1ss_set_be, .disable_eq = rtw89_pci_disable_eq_be, + .power_wake = _patch_pcie_power_wake_be, }; EXPORT_SYMBOL(rtw89_pci_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index f24aca663cf0..4e3754fd18fd 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include "acpi.h" #include "chan.h" #include "coex.h" #include "debug.h" @@ -263,16 +264,26 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES, static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, const struct rtw89_chan *chan, bool *fix_giltf_en, u8 *fix_giltf) { struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); - u8 he_gi = mask->control[nl_band].he_gi; u8 he_ltf = mask->control[nl_band].he_ltf; + u8 he_gi = mask->control[nl_band].he_gi; - if (!rtwsta_link->use_cfg_mask) + *fix_giltf_en = true; + + if (rtwdev->chip->chip_id == RTL8852C && + chan->band_width == RTW89_CHANNEL_WIDTH_160 && + rtw89_sta_link_has_su_mu_4xhe08(link_sta)) + *fix_giltf = RTW89_GILTF_SGI_4XHE08; + else + *fix_giltf = RTW89_GILTF_2XHE08; + + if (!(rtwsta_link->use_cfg_mask && link_sta->he_cap.has_he)) return; if (he_ltf == 2 && he_gi == 2) { @@ -287,12 +298,7 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, *fix_giltf = RTW89_GILTF_1XHE16; } else if (he_ltf == 0 && he_gi == 0) { *fix_giltf = RTW89_GILTF_1XHE08; - } else { - *fix_giltf_en = false; - return; } - - *fix_giltf_en = true; } static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, @@ -325,6 +331,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, mode |= RTW89_RA_MODE_EHT; ra_mask |= get_eht_ra_mask(link_sta); high_rate_masks = rtw89_ra_mask_eht_rates; + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta, + chan, &fix_giltf_en, &fix_giltf); } else if (link_sta->he_cap.has_he) { mode |= RTW89_RA_MODE_HE; csi_mode = RTW89_RA_RPT_MODE_HE; @@ -336,7 +344,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) ldpc_en = 1; - rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf); + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta, + chan, &fix_giltf_en, &fix_giltf); } else if (link_sta->vht_cap.vht_supported) { u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map); @@ -466,11 +475,11 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->csi_mode = csi_mode; } -static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, - u32 changed) +void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, + u32 changed) { + struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_ra_info *ra = &rtwsta_link->ra; struct ieee80211_link_sta *link_sta; @@ -503,14 +512,11 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta u32 changed) { struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); - struct rtw89_vif_link *rtwvif_link; struct rtw89_sta_link *rtwsta_link; unsigned int link_id; - rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { - rtwvif_link = rtwsta_link->rtwvif_link; - __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed); - } + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + rtw89_phy_ra_update_sta_link(rtwdev, rtwsta_link, changed); } static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, @@ -1854,6 +1860,228 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl); +static u8 rtw89_phy_ant_gain_domain_to_regd(struct rtw89_dev *rtwdev, u8 ant_gain_regd) +{ + switch (ant_gain_regd) { + case RTW89_ANT_GAIN_ETSI: + return RTW89_ETSI; + default: + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "unknown antenna gain domain: %d\n", + ant_gain_regd); + return RTW89_REGD_NUM; + } +} + +/* antenna gain in unit of 0.25 dbm */ +#define RTW89_ANT_GAIN_2GHZ_MIN -8 +#define RTW89_ANT_GAIN_2GHZ_MAX 14 +#define RTW89_ANT_GAIN_5GHZ_MIN -8 +#define RTW89_ANT_GAIN_5GHZ_MAX 20 +#define RTW89_ANT_GAIN_6GHZ_MIN -8 +#define RTW89_ANT_GAIN_6GHZ_MAX 20 + +#define RTW89_ANT_GAIN_REF_2GHZ 14 +#define RTW89_ANT_GAIN_REF_5GHZ 20 +#define RTW89_ANT_GAIN_REF_6GHZ 20 + +void rtw89_phy_ant_gain_init(struct rtw89_dev *rtwdev) +{ + struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_acpi_rtag_result res = {}; + u32 domain; + int ret; + u8 i, j; + u8 regd; + u8 val; + + if (!chip->support_ant_gain) + return; + + ret = rtw89_acpi_evaluate_rtag(rtwdev, &res); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "acpi: cannot eval rtag: %d\n", ret); + return; + } + + if (res.revision != 0) { + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "unknown rtag revision: %d\n", res.revision); + return; + } + + domain = get_unaligned_le32(&res.domain); + + for (i = 0; i < RTW89_ANT_GAIN_DOMAIN_NUM; i++) { + if (!(domain & BIT(i))) + continue; + + regd = rtw89_phy_ant_gain_domain_to_regd(rtwdev, i); + if (regd >= RTW89_REGD_NUM) + continue; + ant_gain->regd_enabled |= BIT(regd); + } + + for (i = 0; i < RTW89_ANT_GAIN_CHAIN_NUM; i++) { + for (j = 0; j < RTW89_ANT_GAIN_SUBBAND_NR; j++) { + val = res.ant_gain_table[i][j]; + switch (j) { + default: + case RTW89_ANT_GAIN_2GHZ_SUBBAND: + val = RTW89_ANT_GAIN_REF_2GHZ - + clamp_t(s8, val, + RTW89_ANT_GAIN_2GHZ_MIN, + RTW89_ANT_GAIN_2GHZ_MAX); + break; + case RTW89_ANT_GAIN_5GHZ_SUBBAND_1: + case RTW89_ANT_GAIN_5GHZ_SUBBAND_2: + case RTW89_ANT_GAIN_5GHZ_SUBBAND_2E: + case RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4: + val = RTW89_ANT_GAIN_REF_5GHZ - + clamp_t(s8, val, + RTW89_ANT_GAIN_5GHZ_MIN, + RTW89_ANT_GAIN_5GHZ_MAX); + break; + case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L: + case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H: + case RTW89_ANT_GAIN_6GHZ_SUBBAND_6: + case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L: + case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H: + case RTW89_ANT_GAIN_6GHZ_SUBBAND_8: + val = RTW89_ANT_GAIN_REF_6GHZ - + clamp_t(s8, val, + RTW89_ANT_GAIN_6GHZ_MIN, + RTW89_ANT_GAIN_6GHZ_MAX); + } + ant_gain->offset[i][j] = val; + } + } +} + +static +enum rtw89_ant_gain_subband rtw89_phy_ant_gain_get_subband(struct rtw89_dev *rtwdev, + u32 center_freq) +{ + switch (center_freq) { + default: + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "center freq: %u to antenna gain subband is unhandled\n", + center_freq); + fallthrough; + case 2412 ... 2484: + return RTW89_ANT_GAIN_2GHZ_SUBBAND; + case 5180 ... 5240: + return RTW89_ANT_GAIN_5GHZ_SUBBAND_1; + case 5250 ... 5320: + return RTW89_ANT_GAIN_5GHZ_SUBBAND_2; + case 5500 ... 5720: + return RTW89_ANT_GAIN_5GHZ_SUBBAND_2E; + case 5745 ... 5885: + return RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4; + case 5955 ... 6155: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L; + case 6175 ... 6415: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H; + case 6435 ... 6515: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_6; + case 6535 ... 6695: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L; + case 6715 ... 6855: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H; + + /* freq 6875 (ch 185, 20MHz) spans RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H + * and RTW89_ANT_GAIN_6GHZ_SUBBAND_8, so directly describe it with + * struct rtw89_6ghz_span. + */ + + case 6895 ... 7115: + return RTW89_ANT_GAIN_6GHZ_SUBBAND_8; + } +} + +static s8 rtw89_phy_ant_gain_query(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, u32 center_freq) +{ + struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain; + enum rtw89_ant_gain_subband subband_l, subband_h; + const struct rtw89_6ghz_span *span; + + span = rtw89_get_6ghz_span(rtwdev, center_freq); + + if (span && RTW89_ANT_GAIN_SPAN_VALID(span)) { + subband_l = span->ant_gain_subband_low; + subband_h = span->ant_gain_subband_high; + } else { + subband_l = rtw89_phy_ant_gain_get_subband(rtwdev, center_freq); + subband_h = subband_l; + } + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "center_freq %u: antenna gain subband {%u, %u}\n", + center_freq, subband_l, subband_h); + + return min(ant_gain->offset[path][subband_l], + ant_gain->offset[path][subband_h]); +} + +static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 center_freq) +{ + struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain; + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 regd = rtw89_regd_get(rtwdev, band); + s8 offset_patha, offset_pathb; + + if (!chip->support_ant_gain) + return 0; + + if (!(ant_gain->regd_enabled & BIT(regd))) + return 0; + + offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq); + offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq); + + return max(offset_patha, offset_pathb); +} + +s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain; + u8 regd = rtw89_regd_get(rtwdev, chan->band_type); + s8 offset_patha, offset_pathb; + + if (!(ant_gain->regd_enabled & BIT(regd))) + return 0; + + offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq); + offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq); + + return rtw89_phy_txpwr_rf_to_bb(rtwdev, offset_patha - offset_pathb); +} +EXPORT_SYMBOL(rtw89_phy_ant_gain_pwr_offset); + +void rtw89_print_ant_gain(struct seq_file *m, struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain; + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 regd = rtw89_regd_get(rtwdev, chan->band_type); + s8 offset_patha, offset_pathb; + + if (!chip->support_ant_gain || !(ant_gain->regd_enabled & BIT(regd))) { + seq_puts(m, "no DAG is applied\n"); + return; + } + + offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq); + offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq); + + seq_printf(m, "ChainA offset: %d dBm\n", offset_patha); + seq_printf(m, "ChainB offset: %d dBm\n", offset_pathb); +} + static const u8 rtw89_rs_idx_num_ax[] = { [RTW89_RS_CCK] = RTW89_RATE_CCK_NUM, [RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM, @@ -1917,20 +2145,6 @@ void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate); -static s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf) -{ - const struct rtw89_chip_info *chip = rtwdev->chip; - - return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac); -} - -static s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm) -{ - const struct rtw89_chip_info *chip = rtwdev->chip; - - return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63); -} - static s8 rtw89_phy_txpwr_dbm_without_tolerance(s8 dbm) { const u8 tssi_deviation_point = 0; @@ -2027,7 +2241,7 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); u8 reg6 = regulatory->reg_6ghz_power; - s8 lmt = 0, sar; + s8 lmt = 0, sar, offset; s8 cstr; switch (band) { @@ -2059,7 +2273,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, return 0; } - lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt); + offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq); + lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt + offset); sar = rtw89_query_sar(rtwdev, freq); cstr = rtw89_phy_get_tpe_constraint(rtwdev, band); @@ -2286,7 +2501,7 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); u8 reg6 = regulatory->reg_6ghz_power; - s8 lmt_ru = 0, sar; + s8 lmt_ru = 0, sar, offset; s8 cstr; switch (band) { @@ -2318,7 +2533,8 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, return 0; } - lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru); + offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq); + lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru + offset); sar = rtw89_query_sar(rtwdev, freq); cstr = rtw89_phy_get_tpe_constraint(rtwdev, band); @@ -3228,10 +3444,16 @@ rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u3 (int)(len - sizeof(report->hdr)), &report->state); } +static void +rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ +} + static void (* const rtw89_phy_c2h_rfk_report_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { [RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE] = rtw89_phy_c2h_rfk_report_state, + [RTW89_PHY_C2H_RFK_LOG_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr, }; bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func) @@ -3285,11 +3507,11 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, return; fallthrough; default: - rtw89_info(rtwdev, "c2h class %d not support\n", class); + rtw89_info(rtwdev, "PHY c2h class %d not support\n", class); return; } if (!handler) { - rtw89_info(rtwdev, "c2h class %d func %d not support\n", class, + rtw89_info(rtwdev, "PHY c2h class %d func %d not support\n", class, func); return; } @@ -4058,7 +4280,6 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev, if (!force && cfo->crystal_cap == crystal_cap) return; - crystal_cap = clamp_t(u8, crystal_cap, 0, 127); if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) { rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap); rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap); @@ -4181,7 +4402,7 @@ static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev, s32 curr_cfo) { struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking; - s8 crystal_cap = cfo->crystal_cap; + int crystal_cap = cfo->crystal_cap; s32 cfo_abs = abs(curr_cfo); int sign; @@ -4202,15 +4423,17 @@ static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev, } sign = curr_cfo > 0 ? 1 : -1; if (cfo_abs > CFO_TRK_STOP_TH_4) - crystal_cap += 7 * sign; + crystal_cap += 3 * sign; else if (cfo_abs > CFO_TRK_STOP_TH_3) - crystal_cap += 5 * sign; - else if (cfo_abs > CFO_TRK_STOP_TH_2) crystal_cap += 3 * sign; + else if (cfo_abs > CFO_TRK_STOP_TH_2) + crystal_cap += 1 * sign; else if (cfo_abs > CFO_TRK_STOP_TH_1) crystal_cap += 1 * sign; else return; + + crystal_cap = clamp(crystal_cap, 0, 127); rtw89_phy_cfo_set_crystal_cap(rtwdev, (u8)crystal_cap, false); rtw89_debug(rtwdev, RTW89_DBG_CFO, "X_cap{Curr,Default}={0x%x,0x%x}\n", @@ -6310,6 +6533,12 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_chip_cfg_txrx_path(rtwdev); } +void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev) +{ + rtw89_phy_env_monitor_init(rtwdev); + rtw89_physts_parsing_init(rtwdev); +} + void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index c683f4d7d29b..697ee47fe325 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -57,7 +57,7 @@ #define CFO_TRK_STOP_TH_4 (30 << 2) #define CFO_TRK_STOP_TH_3 (20 << 2) #define CFO_TRK_STOP_TH_2 (10 << 2) -#define CFO_TRK_STOP_TH_1 (00 << 2) +#define CFO_TRK_STOP_TH_1 (03 << 2) #define CFO_TRK_STOP_TH (2 << 2) #define CFO_SW_COMP_FINE_TUNE (2 << 2) #define CFO_PERIOD_CNT 15 @@ -151,6 +151,7 @@ enum rtw89_phy_c2h_rfk_log_func { enum rtw89_phy_c2h_rfk_report_func { RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE = 0, + RTW89_PHY_C2H_RFK_LOG_TAS_PWR = 6, }; enum rtw89_phy_c2h_dm_func { @@ -813,6 +814,7 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, void *extra_data); void rtw89_phy_dm_init(struct rtw89_dev *rtwdev); +void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev); void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, enum rtw89_phy_idx phy_idx); void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, @@ -826,6 +828,11 @@ s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev, const struct rtw89_rate_desc *desc); s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw, const struct rtw89_rate_desc *rate_desc); +void rtw89_phy_ant_gain_init(struct rtw89_dev *rtwdev); +s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan); +void rtw89_print_ant_gain(struct seq_file *m, struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan); void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev, const struct rtw89_txpwr_table *tbl); s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, @@ -896,10 +903,34 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev, phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx); } +static inline s8 rtw89_phy_txpwr_rf_to_bb(struct rtw89_dev *rtwdev, s8 txpwr_rf) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + return txpwr_rf << (chip->txpwr_factor_bb - chip->txpwr_factor_rf); +} + +static inline s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac); +} + +static inline s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63); +} + void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, u32 changed); +void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, + u32 changed); void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask); diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index c1c12abc2ea9..96ea04d90cd3 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -8,6 +8,7 @@ #include "debug.h" #include "fw.h" #include "mac.h" +#include "phy.h" #include "ps.h" #include "reg.h" #include "util.h" @@ -62,11 +63,8 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_power_mode_change(rtwdev, enter); } -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev) { - if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) - return; - if (!rtwdev->ps_mode) return; @@ -85,8 +83,8 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) rtw89_ps_power_mode_change(rtwdev, false); } -static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) +static void __rtw89_enter_lps_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { .macid = rtwvif_link->mac_id, @@ -96,7 +94,6 @@ static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL); rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); - rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link); } static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, @@ -121,17 +118,32 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); } -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool ps_mode) { + struct rtw89_vif_link *rtwvif_link; + bool can_ps_mode = true; + unsigned int link_id; + lockdep_assert_held(&rtwdev->mutex); if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) return; - __rtw89_enter_lps(rtwdev, rtwvif_link); - if (ps_mode) - __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + __rtw89_enter_lps_link(rtwdev, rtwvif_link); + + if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + can_ps_mode = false; + } + + if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw)) + rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); + else + rtw89_fw_h2c_lps_ml_cmn_info(rtwdev, rtwvif); + + if (ps_mode && can_ps_mode) + __rtw89_enter_ps_mode(rtwdev); } static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, @@ -157,6 +169,8 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); + rtw89_phy_dm_reinit(rtwdev); + rtw89_for_each_rtwvif(rtwdev, rtwvif) rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) rtw89_leave_lps_vif(rtwdev, rtwvif_link); @@ -282,12 +296,6 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; int count = 0; - /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode() - * to take MLO cases into account before doing the following. - */ - if (rtwdev->support_mlo) - goto disable_lps; - mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) goto disable_lps; diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index cdd712966b09..2b88f254a32d 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -5,11 +5,11 @@ #ifndef __RTW89_PS_H_ #define __RTW89_PS_H_ -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool ps_mode); void rtw89_leave_lps(struct rtw89_dev *rtwdev); void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev); void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 18ec7c0252fb..10d0efa7a58e 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -7447,6 +7447,10 @@ #define B_BE_CSIPRT_HESU_AID_EN BIT(25) #define B_BE_CSIPRT_VHTSU_AID_EN BIT(24) +#define R_BE_DRV_INFO_OPTION 0x11470 +#define R_BE_DRV_INFO_OPTION_C1 0x15470 +#define B_BE_DRV_INFO_PHYRPT_EN BIT(0) + #define R_BE_RX_ERR_ISR 0x114F4 #define R_BE_RX_ERR_ISR_C1 0x154F4 #define B_BE_RX_ERR_TRIG_ACT_TO BIT(9) diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index cad5189708e7..80b2f74589eb 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -17,7 +17,7 @@ static const struct rtw89_regd rtw89_ww_regd = static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC), - COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE), COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC), @@ -35,7 +35,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), @@ -72,7 +72,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), @@ -82,13 +82,13 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR), COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -101,7 +101,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE), COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN), @@ -110,12 +110,12 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC), COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI), - COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_THAILAND), + COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND), COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), @@ -158,9 +158,9 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), @@ -176,12 +176,12 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -194,19 +194,19 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -216,15 +216,15 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC), - COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA), @@ -237,9 +237,9 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), - COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -247,13 +247,16 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA), COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SY", RTW89_ETSI, RTW89_NA, RTW89_NA), + COUNTRY_REGD("SD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), }; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 68c67a763f4d..c56f70267882 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2298,7 +2298,8 @@ static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]); for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); @@ -2391,6 +2392,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .ctrl_btg_bt_rx = rtw8851b_ctrl_btg_bt_rx, .query_ppdu = rtw8851b_query_ppdu, .convert_rpl_to_rssi = NULL, + .phy_rpt_to_rssi = NULL, .ctrl_nbtg_bt_tx = rtw8851b_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset, @@ -2464,6 +2466,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .nctl_post_table = &rtw8851b_nctl_post_defs_tbl, .dflt_parms = &rtw89_8851b_dflt_parms, .rfe_parms_conf = rtw89_8851b_rfe_parms_conf, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -2479,6 +2482,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80), .support_unii4 = true, + .support_ant_gain = false, .ul_tb_waveform_ctrl = true, .ul_tb_pwr_diff = false, .hw_sec_hdr = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c index 364e36354225..f72b3ac6f149 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c @@ -2199,7 +2199,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, if (dgain > 0x5fc || dgain < 0x556) { _dpk_one_shot(rtwdev, phy, path, D_SYNC); - dgain = _dpk_dgain_read(rtwdev); + _dpk_dgain_read(rtwdev); } if (agc_cnt == 0) { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index e647759ebd69..9bd2842c27d5 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2068,7 +2068,9 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B])); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], + rx_power[RF_PATH_B])); for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); @@ -2116,6 +2118,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .ctrl_btg_bt_rx = rtw8852a_ctrl_btg_bt_rx, .query_ppdu = rtw8852a_query_ppdu, .convert_rpl_to_rssi = NULL, + .phy_rpt_to_rssi = NULL, .ctrl_nbtg_bt_tx = rtw8852a_ctrl_nbtg_bt_tx, .cfg_txrx_path = NULL, .set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset, @@ -2181,6 +2184,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .nctl_post_table = NULL, .dflt_parms = &rtw89_8852a_dflt_parms, .rfe_parms_conf = NULL, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = &rtw89_8852a_phy_dig_table, @@ -2196,6 +2200,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80), .support_unii4 = false, + .support_ant_gain = false, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = false, .hw_sec_hdr = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 49a319128316..dfb2bf61b0b8 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -745,6 +745,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, + .phy_rpt_to_rssi = NULL, .ctrl_nbtg_bt_tx = rtw8852bx_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset, @@ -819,6 +820,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .nctl_post_table = NULL, .dflt_parms = &rtw89_8852b_dflt_parms, .rfe_parms_conf = NULL, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -834,6 +836,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80), .support_unii4 = true, + .support_ant_gain = true, .ul_tb_waveform_ctrl = true, .ul_tb_pwr_diff = false, .hw_sec_hdr = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c index f4aa4437fb75..0e094ce9c9b0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c @@ -1206,24 +1206,25 @@ void __rtw8852bx_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_cha } static u32 rtw8852bx_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx, s16 ref) + enum rtw89_phy_idx phy_idx, + s16 ref, u16 pwr_ofst_decrease) { const u16 tssi_16dbm_cw = 0x12c; const u8 base_cw_0db = 0x27; - const s8 ofst_int = 0; s16 pwr_s10_3; s16 rf_pwr_cw; u16 bb_pwr_cw; u32 pwr_cw; u32 tssi_ofst_cw; - pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); + pwr_s10_3 = (ref << 1) + (s16)(base_cw_0db << 3) - pwr_ofst_decrease; bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0)); rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3)); rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; - tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); + tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)) - + pwr_ofst_decrease; rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); @@ -1234,10 +1235,11 @@ static u32 rtw8852bx_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, } static void rtw8852bx_set_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) + enum rtw89_phy_idx phy_idx, s16 pwr_ofst) { static const u32 addr[RF_PATH_NUM_8852BX] = {0x5800, 0x7800}; const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF; + u16 ofst_dec[RF_PATH_NUM_8852BX]; const u8 ofst_ofdm = 0x4; const u8 ofst_cck = 0x8; const s16 ref_ofdm = 0; @@ -1250,19 +1252,20 @@ static void rtw8852bx_set_txpwr_ref(struct rtw89_dev *rtwdev, rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, B_AX_PWR_REF, 0x0); - rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); - val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); + ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? 0 : abs(pwr_ofst); + ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ofst : 0; - for (i = 0; i < RF_PATH_NUM_8852BX; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, - phy_idx); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); + for (i = 0; i < RF_PATH_NUM_8852BX; i++) { + val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, phy_idx); + } rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); - val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); - - for (i = 0; i < RF_PATH_NUM_8852BX; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, - phy_idx); + for (i = 0; i < RF_PATH_NUM_8852BX; i++) { + val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, phy_idx); + } } static void rtw8852bx_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, @@ -1333,6 +1336,16 @@ static void rtw8852bx_set_tx_shape(struct rtw89_dev *rtwdev, tx_shape_ofdm); } +static void rtw8852bx_set_txpwr_diff(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + s16 pwr_ofst; + + pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan); + rtw8852bx_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst); +} + static void __rtw8852bx_set_txpwr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) @@ -1342,12 +1355,13 @@ static void __rtw8852bx_set_txpwr(struct rtw89_dev *rtwdev, rtw8852bx_set_tx_shape(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); + rtw8852bx_set_txpwr_diff(rtwdev, chan, phy_idx); } static void __rtw8852bx_set_txpwr_ctrl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { - rtw8852bx_set_txpwr_ref(rtwdev, phy_idx); + rtw8852bx_set_txpwr_ref(rtwdev, phy_idx, 0); } static @@ -1936,7 +1950,9 @@ static void __rtw8852bx_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B])); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], + rx_power[RF_PATH_B])); for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index 876725133228..bde3e1fb7ca6 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -679,6 +679,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx, .query_ppdu = rtw8852bx_query_ppdu, .convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi, + .phy_rpt_to_rssi = NULL, .ctrl_nbtg_bt_tx = rtw8852bx_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset, @@ -752,6 +753,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .nctl_post_table = NULL, .dflt_parms = NULL, .rfe_parms_conf = NULL, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -767,6 +769,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { BIT(NL80211_CHAN_WIDTH_40) | BIT(NL80211_CHAN_WIDTH_80), .support_unii4 = true, + .support_ant_gain = true, .ul_tb_waveform_ctrl = true, .ul_tb_pwr_diff = false, .hw_sec_hdr = false, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index cde34f8e1e67..bc84b15e7826 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1882,9 +1882,9 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) } static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx, s16 ref) + enum rtw89_phy_idx phy_idx, + s16 ref, u16 pwr_ofst_decrease) { - s8 ofst_int = 0; u8 base_cw_0db = 0x27; u16 tssi_16dbm_cw = 0x12c; s16 pwr_s10_3 = 0; @@ -1893,13 +1893,14 @@ static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, u32 pwr_cw = 0; u32 tssi_ofst_cw = 0; - pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); + pwr_s10_3 = (ref << 1) + (s16)(base_cw_0db << 3) - pwr_ofst_decrease; bb_pwr_cw = FIELD_GET(GENMASK(2, 0), pwr_s10_3); rf_pwr_cw = FIELD_GET(GENMASK(8, 3), pwr_s10_3); rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; - tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); + tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)) - + pwr_ofst_decrease; rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); @@ -1943,9 +1944,10 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, } static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) + enum rtw89_phy_idx phy_idx, s16 pwr_ofst) { static const u32 addr[RF_PATH_NUM_8852C] = {0x5800, 0x7800}; + u16 ofst_dec[RF_PATH_NUM_8852C]; const u32 mask = 0x7FFFFFF; const u8 ofst_ofdm = 0x4; const u8 ofst_cck = 0x8; @@ -1959,19 +1961,20 @@ static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev, rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, GENMASK(27, 10), 0x0); - rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); - val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); + ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? 0 : abs(pwr_ofst); + ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ofst : 0; - for (i = 0; i < RF_PATH_NUM_8852C; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, - phy_idx); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); + for (i = 0; i < RF_PATH_NUM_8852C; i++) { + val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, phy_idx); + } rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); - val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); - - for (i = 0; i < RF_PATH_NUM_8852C; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, - phy_idx); + for (i = 0; i < RF_PATH_NUM_8852C; i++) { + val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, phy_idx); + } } static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, @@ -2052,6 +2055,16 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev, B_P1_DAC_COMP_POST_DPD_EN); } +static void rtw8852c_set_txpwr_diff(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + s16 pwr_ofst; + + pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan); + rtw8852c_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst); +} + static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) @@ -2061,12 +2074,13 @@ static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev, rtw8852c_set_tx_shape(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); + rtw8852c_set_txpwr_diff(rtwdev, chan, phy_idx); } static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { - rtw8852c_set_txpwr_ref(rtwdev, phy_idx); + rtw8852c_set_txpwr_ref(rtwdev, phy_idx, 0); } static void @@ -2793,7 +2807,10 @@ static void rtw8852c_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B])); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], + rx_power[RF_PATH_B])); + for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); @@ -2893,6 +2910,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx, .query_ppdu = rtw8852c_query_ppdu, .convert_rpl_to_rssi = NULL, + .phy_rpt_to_rssi = NULL, .ctrl_nbtg_bt_tx = rtw8852c_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8852c_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, @@ -2959,6 +2977,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .dflt_parms = &rtw89_8852c_dflt_parms, .rfe_parms_conf = NULL, .chanctx_listener = &rtw8852c_chanctx_listener, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -2976,6 +2995,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { BIT(NL80211_CHAN_WIDTH_80) | BIT(NL80211_CHAN_WIDTH_160), .support_unii4 = true, + .support_ant_gain = true, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = true, .hw_sec_hdr = true, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index bd17c0a1c684..b92e2ce4f4ad 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -1769,10 +1769,10 @@ u8 _rx_dck_channel_calc(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan) target_ch = chan->channel - 33; } } else if (chan->band_type == RTW89_BAND_6G) { - if (chan->channel >= 1 && chan->channel <= 125) - target_ch = chan->channel + 32; - else + if (chan->channel > 125) target_ch = chan->channel - 32; + else + target_ch = chan->channel + 32; } else { target_ch = chan->channel; } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 9a4db04a1967..f04cb3b11372 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -14,7 +14,7 @@ #include "rtw8922a_rfk.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 2 +#define RTW8922A_FW_FORMAT_MAX 3 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" @@ -2565,8 +2565,10 @@ static void rtw8922a_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = - RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B])); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], + rx_power[RF_PATH_B])); + for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); @@ -2607,6 +2609,16 @@ static void rtw8922a_convert_rpl_to_rssi(struct rtw89_dev *rtwdev, phy_ppdu->rssi_avg = phy_ppdu->rpl_avg; } +static void rtw8922a_phy_rpt_to_rssi(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status) +{ + if (desc_info->rssi <= 0x1 || (desc_info->rssi >> 2) > MAX_RSSI) + return; + + rx_status->signal = (desc_info->rssi >> 2) - MAX_RSSI; +} + static int rtw8922a_mac_enable_bb_rf(struct rtw89_dev *rtwdev) { rtw89_write8_set(rtwdev, R_BE_FEN_RST_ENABLE, @@ -2665,6 +2677,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .ctrl_btg_bt_rx = rtw8922a_ctrl_btg_bt_rx, .query_ppdu = rtw8922a_query_ppdu, .convert_rpl_to_rssi = rtw8922a_convert_rpl_to_rssi, + .phy_rpt_to_rssi = rtw8922a_phy_rpt_to_rssi, .ctrl_nbtg_bt_tx = rtw8922a_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8922a_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = NULL, @@ -2729,6 +2742,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .nctl_post_table = NULL, .dflt_parms = NULL, /* load parm from fw */ .rfe_parms_conf = NULL, /* load parm from fw */ + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -2746,6 +2760,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { BIT(NL80211_CHAN_WIDTH_80) | BIT(NL80211_CHAN_WIDTH_160), .support_unii4 = true, + .support_ant_gain = false, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = false, .hw_sec_hdr = true, diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index bcc287771b2a..871f45a6508c 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -42,7 +42,7 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev, /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with - * struct rtw89_sar_span in the following. + * struct rtw89_6ghz_span. */ case 6895 ... 7115: @@ -50,63 +50,18 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev, } } -struct rtw89_sar_span { - enum rtw89_sar_subband subband_low; - enum rtw89_sar_subband subband_high; -}; - -#define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high) - -#define RTW89_SAR_6GHZ_SPAN_HEAD 6145 -#define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \ - ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2) - -#define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \ - [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \ - .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \ - .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \ - } - -/* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR - * subbands. In the following, we describe each of them with rtw89_sar_span. - */ -static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = { - RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H), - RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H), - RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H), - RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L), - RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L), - RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L), - RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H), - RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H), - RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8), - RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8), - RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8), - RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8), -}; - static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, u32 center_freq, s32 *cfg) { struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; - const struct rtw89_sar_span *span = NULL; enum rtw89_sar_subband subband_l, subband_h; - int idx; - - if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) { - idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq); - /* To decrease size of rtw89_sar_overlapping_6ghz[], - * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs - * to make first span as index 0 of the table. So, if center - * frequency is less than the first one, it will get netative. - */ - if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz)) - span = &rtw89_sar_overlapping_6ghz[idx]; - } + const struct rtw89_6ghz_span *span; + + span = rtw89_get_6ghz_span(rtwdev, center_freq); if (span && RTW89_SAR_SPAN_VALID(span)) { - subband_l = span->subband_low; - subband_h = span->subband_high; + subband_l = span->sar_subband_low; + subband_h = span->sar_subband_high; } else { subband_l = rtw89_sar_get_subband(rtwdev, center_freq); subband_h = subband_l; diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 7b203bb7f151..26a944d3b672 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -365,6 +365,7 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev) ser_reset_vif(rtwdev, rtwvif); rtwdev->total_sta_assoc = 0; + refcount_set(&rtwdev->refcount_ap_info, 0); } /* hal function */ diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index b2e47829983f..70fe7cebc9d5 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -560,6 +560,9 @@ struct rtw89_phy_sts_iehdr { #define BE_RXD_HDR_OFFSET_MASK GENMASK(20, 16) #define BE_RXD_WL_HD_IV_LEN_MASK GENMASK(26, 21) +/* BE RXD - PHY RPT dword0 */ +#define BE_RXD_PHY_RSSI GENMASK(11, 0) + struct rtw89_phy_sts_ie00 { __le32 w0; __le32 w1; diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 3e81fd974ec1..01754d031bb4 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -620,7 +620,10 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, * need to unlock mutex */ mutex_unlock(&rtwdev->mutex); - key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1); + if (ieee80211_vif_is_mld(wow_vif)) + key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, rtwvif_link->link_id); + else + key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1); mutex_lock(&rtwdev->mutex); kfree(rekey_conf); @@ -691,9 +694,7 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) { - struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - - __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + __rtw89_enter_ps_mode(rtwdev); } static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) @@ -701,7 +702,7 @@ static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) - rtw89_enter_lps(rtwdev, rtwvif_link, false); + rtw89_enter_lps(rtwdev, rtwvif_link->rtwvif, false); else if (rtw89_wow_no_link(rtwdev)) rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true); } |