mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 06:49:29 -04:00
Merge tag 'rtw-next-2025-05-16' of https://github.com/pkshih/rtw
Ping-Ke Shih says: ================== rtw-next patches for v6.16 Some fixes and refinements across drivers, and regular development of MLO and STA + P2P concurrency. Major changes are listed below. rtw88: * improve throughput for RTL8814AU rtw89: * support MLO * improve user experience for STA + P2P concurrency * dynamic antenna gain (DAG) with different power by antenna * load SAR tables from ACPI ================== Link: https://patch.msgid.link/17e74675-70cc-43d7-a797-afb937030d34@RTEXMBS04.realtek.com.tw/ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -58,17 +58,6 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_rfreg_delay);
|
||||
|
||||
void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data)
|
||||
{
|
||||
if (addr >= 0xf9 && addr <= 0xfe) {
|
||||
rtl_addr_delay(addr);
|
||||
} else {
|
||||
rtl_set_bbreg(hw, addr, MASKDWORD, data);
|
||||
udelay(1);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_bb_delay);
|
||||
|
||||
static void rtl_fw_do_work(const struct firmware *firmware, void *context,
|
||||
bool is_wow)
|
||||
{
|
||||
|
||||
@@ -58,7 +58,6 @@ void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context);
|
||||
void rtl_addr_delay(u32 addr);
|
||||
void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
|
||||
u32 mask, u32 data);
|
||||
void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data);
|
||||
bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
bool rtl_btc_status_false(void);
|
||||
void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval);
|
||||
|
||||
@@ -155,6 +155,16 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
|
||||
((u8)init_aspm) == (PCI_EXP_LNKCTL_ASPM_L0S |
|
||||
PCI_EXP_LNKCTL_ASPM_L1 | PCI_EXP_LNKCTL_CCC))
|
||||
ppsc->support_aspm = false;
|
||||
|
||||
/* RTL8723BE found on some ASUSTek laptops, such as F441U and
|
||||
* X555UQ with subsystem ID 11ad:1723 are known to output large
|
||||
* amounts of PCIe AER errors during and after boot up, causing
|
||||
* heavy lags, poor network throughput, and occasional lock-ups.
|
||||
*/
|
||||
if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
|
||||
(rtlpci->pdev->subsystem_vendor == 0x11ad &&
|
||||
rtlpci->pdev->subsystem_device == 0x1723))
|
||||
ppsc->support_aspm = false;
|
||||
}
|
||||
|
||||
static bool _rtl_pci_platform_switch_device_pci_aspm(
|
||||
|
||||
@@ -2055,11 +2055,6 @@ void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
|
||||
RTPRINT(rtlpriv, FINIT, INIT_IQK, "LCK:Finish!!!\n");
|
||||
}
|
||||
|
||||
void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
|
||||
u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid,
|
||||
u32 para1, u32 para2, u32 msdelay)
|
||||
|
||||
@@ -83,7 +83,6 @@ void rtl92d_phy_set_poweron(struct ieee80211_hw *hw);
|
||||
bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw);
|
||||
void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
|
||||
void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw);
|
||||
void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta);
|
||||
void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
|
||||
void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
|
||||
|
||||
|
||||
@@ -2445,11 +2445,6 @@ void rtl92du_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
|
||||
RTPRINT(rtlpriv, FINIT, INIT_IQK, "LCK:Finish!!!\n");
|
||||
}
|
||||
|
||||
void rtl92du_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
u8 rtl92du_phy_sw_chnl(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
@@ -24,7 +24,6 @@ void rtl92du_phy_set_poweron(struct ieee80211_hw *hw);
|
||||
bool rtl92du_phy_check_poweroff(struct ieee80211_hw *hw);
|
||||
void rtl92du_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
|
||||
void rtl92du_update_bbrf_configuration(struct ieee80211_hw *hw);
|
||||
void rtl92du_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta);
|
||||
void rtl92du_phy_iq_calibrate(struct ieee80211_hw *hw);
|
||||
void rtl92du_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
|
||||
void rtl92du_phy_init_pa_bias(struct ieee80211_hw *hw);
|
||||
|
||||
@@ -2926,10 +2926,6 @@ void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw)
|
||||
rtlphy->lck_inprogress = false;
|
||||
}
|
||||
|
||||
void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta)
|
||||
{
|
||||
}
|
||||
|
||||
void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
|
||||
{
|
||||
_rtl92ee_phy_set_rfpath_switch(hw, bmain, false);
|
||||
|
||||
@@ -119,7 +119,6 @@ void rtl92ee_phy_set_bw_mode(struct ieee80211_hw *hw,
|
||||
void rtl92ee_phy_sw_chnl_callback(struct ieee80211_hw *hw);
|
||||
u8 rtl92ee_phy_sw_chnl(struct ieee80211_hw *hw);
|
||||
void rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
|
||||
void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta);
|
||||
void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw);
|
||||
void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
|
||||
bool rtl92ee_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
|
||||
|
||||
@@ -4586,10 +4586,6 @@ void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw)
|
||||
{
|
||||
}
|
||||
|
||||
void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta)
|
||||
{
|
||||
}
|
||||
|
||||
void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
|
||||
{
|
||||
_rtl8821ae_phy_set_rfpath_switch(hw, bmain);
|
||||
|
||||
@@ -214,7 +214,6 @@ void rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw,
|
||||
bool b_recovery);
|
||||
void rtl8812ae_phy_iq_calibrate(struct ieee80211_hw *hw,
|
||||
bool b_recovery);
|
||||
void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, s8 delta);
|
||||
void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw);
|
||||
void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
|
||||
bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
|
||||
|
||||
@@ -1077,15 +1077,3 @@ void rtl_usb_disconnect(struct usb_interface *intf)
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_usb_disconnect);
|
||||
|
||||
int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_usb_suspend);
|
||||
|
||||
int rtl_usb_resume(struct usb_interface *pusb_intf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_usb_resume);
|
||||
|
||||
@@ -138,7 +138,5 @@ int rtl_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id,
|
||||
const struct rtl_hal_cfg *rtl92cu_hal_cfg);
|
||||
void rtl_usb_disconnect(struct usb_interface *intf);
|
||||
int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
|
||||
int rtl_usb_resume(struct usb_interface *pusb_intf);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -309,7 +309,7 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
|
||||
{
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u8 para[2] = {0};
|
||||
u8 para[6] = {};
|
||||
u8 times;
|
||||
u16 tbtt_interval = coex_stat->wl_beacon_interval;
|
||||
|
||||
|
||||
@@ -1466,7 +1466,7 @@ void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
|
||||
int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
|
||||
u8 *buf, u32 size)
|
||||
{
|
||||
u8 bckp[2];
|
||||
u8 bckp[3];
|
||||
u8 val;
|
||||
u16 rsvd_pg_head;
|
||||
u32 bcn_valid_addr;
|
||||
@@ -1478,6 +1478,8 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
bckp[2] = rtw_read8(rtwdev, REG_BCN_CTRL);
|
||||
|
||||
if (rtw_chip_wcpu_11n(rtwdev)) {
|
||||
rtw_write32_set(rtwdev, REG_DWBCN0_CTRL, BIT_BCN_VALID);
|
||||
} else {
|
||||
@@ -1491,6 +1493,9 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
|
||||
val |= BIT_ENSWBCN >> 8;
|
||||
rtw_write8(rtwdev, REG_CR + 1, val);
|
||||
|
||||
rtw_write8(rtwdev, REG_BCN_CTRL,
|
||||
(bckp[2] & ~BIT_EN_BCN_FUNCTION) | BIT_DIS_TSF_UDT);
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) {
|
||||
val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2);
|
||||
bckp[1] = val;
|
||||
@@ -1521,6 +1526,7 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
|
||||
rsvd_pg_head = rtwdev->fifo.rsvd_boundary;
|
||||
rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2,
|
||||
rsvd_pg_head | BIT_BCN_VALID_V1);
|
||||
rtw_write8(rtwdev, REG_BCN_CTRL, bckp[2]);
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE)
|
||||
rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]);
|
||||
rtw_write8(rtwdev, REG_CR + 1, bckp[0]);
|
||||
|
||||
@@ -19,6 +19,8 @@ struct rtw_hci_ops {
|
||||
void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
|
||||
void (*interface_cfg)(struct rtw_dev *rtwdev);
|
||||
void (*dynamic_rx_agg)(struct rtw_dev *rtwdev, bool enable);
|
||||
void (*write_firmware_page)(struct rtw_dev *rtwdev, u32 page,
|
||||
const u8 *data, u32 size);
|
||||
|
||||
int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
|
||||
int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
|
||||
@@ -79,6 +81,12 @@ static inline void rtw_hci_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
|
||||
rtwdev->hci.ops->dynamic_rx_agg(rtwdev, enable);
|
||||
}
|
||||
|
||||
static inline void rtw_hci_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
|
||||
const u8 *data, u32 size)
|
||||
{
|
||||
rtwdev->hci.ops->write_firmware_page(rtwdev, page, data, size);
|
||||
}
|
||||
|
||||
static inline int
|
||||
rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
|
||||
{
|
||||
|
||||
@@ -856,8 +856,8 @@ static void en_download_firmware_legacy(struct rtw_dev *rtwdev, bool en)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size)
|
||||
void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
|
||||
const u8 *data, u32 size)
|
||||
{
|
||||
u32 val32;
|
||||
u32 block_nr;
|
||||
@@ -887,6 +887,7 @@ write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size)
|
||||
rtw_write32(rtwdev, write_addr, le32_to_cpu(remain_data));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_write_firmware_page);
|
||||
|
||||
static int
|
||||
download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size)
|
||||
@@ -904,11 +905,13 @@ download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size)
|
||||
rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT);
|
||||
|
||||
for (page = 0; page < total_page; page++) {
|
||||
write_firmware_page(rtwdev, page, data, DLFW_PAGE_SIZE_LEGACY);
|
||||
rtw_hci_write_firmware_page(rtwdev, page, data,
|
||||
DLFW_PAGE_SIZE_LEGACY);
|
||||
data += DLFW_PAGE_SIZE_LEGACY;
|
||||
}
|
||||
if (last_page_size)
|
||||
write_firmware_page(rtwdev, page, data, last_page_size);
|
||||
rtw_hci_write_firmware_page(rtwdev, page, data,
|
||||
last_page_size);
|
||||
|
||||
if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT, 1)) {
|
||||
rtw_err(rtwdev, "failed to check download firmware report\n");
|
||||
|
||||
@@ -34,6 +34,8 @@ int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
||||
const struct rtw_pwr_seq_cmd * const *cmd_seq);
|
||||
int rtw_mac_power_on(struct rtw_dev *rtwdev);
|
||||
void rtw_mac_power_off(struct rtw_dev *rtwdev);
|
||||
void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
|
||||
const u8 *data, u32 size);
|
||||
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
|
||||
int rtw_mac_init(struct rtw_dev *rtwdev);
|
||||
void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
|
||||
|
||||
@@ -396,6 +396,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (rtw_bf_support)
|
||||
rtw_bf_assoc(rtwdev, vif, conf);
|
||||
|
||||
rtw_set_ampdu_factor(rtwdev, vif, conf);
|
||||
|
||||
rtw_fw_beacon_filter_config(rtwdev, true, vif);
|
||||
} else {
|
||||
rtw_leave_lps(rtwdev);
|
||||
|
||||
@@ -2242,7 +2242,8 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
||||
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
|
||||
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
|
||||
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
|
||||
if (rtwdev->chip->amsdu_in_ampdu)
|
||||
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(hw, TX_AMSDU);
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
@@ -2447,6 +2448,38 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_set_ampdu_factor(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
const struct rtw_chip_ops *ops = rtwdev->chip->ops;
|
||||
struct ieee80211_sta *sta;
|
||||
u8 factor = 0xff;
|
||||
|
||||
if (!ops->set_ampdu_factor)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
rtw_warn(rtwdev, "%s: failed to find station %pM\n",
|
||||
__func__, bss_conf->bssid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta->deflink.vht_cap.vht_supported)
|
||||
factor = u32_get_bits(sta->deflink.vht_cap.cap,
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
|
||||
else if (sta->deflink.ht_cap.ht_supported)
|
||||
factor = sta->deflink.ht_cap.ampdu_factor;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (factor != 0xff)
|
||||
ops->set_ampdu_factor(rtwdev, factor);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless core module");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
@@ -878,6 +878,7 @@ struct rtw_chip_ops {
|
||||
u32 antenna_rx);
|
||||
void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
|
||||
void (*efuse_grant)(struct rtw_dev *rtwdev, bool enable);
|
||||
void (*set_ampdu_factor)(struct rtw_dev *rtwdev, u8 factor);
|
||||
void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
|
||||
void (*phy_calibration)(struct rtw_dev *rtwdev);
|
||||
void (*dpk_track)(struct rtw_dev *rtwdev);
|
||||
@@ -1229,6 +1230,7 @@ struct rtw_chip_info {
|
||||
u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
|
||||
const struct rtw_fwcd_segs *fwcd_segs;
|
||||
|
||||
bool amsdu_in_ampdu;
|
||||
u8 usb_tx_agg_desc_num;
|
||||
bool hw_feature_report;
|
||||
u8 c2h_ra_report_size;
|
||||
@@ -2272,4 +2274,6 @@ void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
|
||||
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
|
||||
bool rtw_core_check_sta_active(struct rtw_dev *rtwdev);
|
||||
void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable);
|
||||
void rtw_set_ampdu_factor(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf);
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "fw.h"
|
||||
#include "ps.h"
|
||||
#include "debug.h"
|
||||
#include "mac.h"
|
||||
|
||||
static bool rtw_disable_msi;
|
||||
static bool rtw_pci_disable_aspm;
|
||||
@@ -1602,6 +1603,7 @@ static const struct rtw_hci_ops rtw_pci_ops = {
|
||||
.link_ps = rtw_pci_link_ps,
|
||||
.interface_cfg = rtw_pci_interface_cfg,
|
||||
.dynamic_rx_agg = NULL,
|
||||
.write_firmware_page = rtw_write_firmware_page,
|
||||
|
||||
.read8 = rtw_pci_read8,
|
||||
.read16 = rtw_pci_read16,
|
||||
|
||||
@@ -519,15 +519,6 @@ static const struct rtw_rqpn rqpn_table_8703b[] = {
|
||||
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
|
||||
};
|
||||
|
||||
/* Default power index table for RTL8703B, used if EFUSE does not
|
||||
* contain valid data. Replaces EFUSE data from offset 0x10 (start of
|
||||
* txpwr_idx_table).
|
||||
*/
|
||||
static const u8 rtw8703b_txpwr_idx_table[] = {
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02
|
||||
};
|
||||
|
||||
static void try_mac_from_devicetree(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct device_node *node = rtwdev->dev->of_node;
|
||||
@@ -544,15 +535,9 @@ static void try_mac_from_devicetree(struct rtw_dev *rtwdev)
|
||||
}
|
||||
}
|
||||
|
||||
#define DBG_EFUSE_FIX(rtwdev, name) \
|
||||
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Fixed invalid EFUSE value: " \
|
||||
# name "=0x%x\n", rtwdev->efuse.name)
|
||||
|
||||
static int rtw8703b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u8 *pwr = (u8 *)efuse->txpwr_idx_table;
|
||||
bool valid = false;
|
||||
int ret;
|
||||
|
||||
ret = rtw8723x_read_efuse(rtwdev, log_map);
|
||||
@@ -562,51 +547,6 @@ static int rtw8703b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
if (!is_valid_ether_addr(efuse->addr))
|
||||
try_mac_from_devicetree(rtwdev);
|
||||
|
||||
/* If TX power index table in EFUSE is invalid, fall back to
|
||||
* built-in table.
|
||||
*/
|
||||
for (int i = 0; i < ARRAY_SIZE(rtw8703b_txpwr_idx_table); i++)
|
||||
if (pwr[i] != 0xff) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
if (!valid) {
|
||||
for (int i = 0; i < ARRAY_SIZE(rtw8703b_txpwr_idx_table); i++)
|
||||
pwr[i] = rtw8703b_txpwr_idx_table[i];
|
||||
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
|
||||
"Replaced invalid EFUSE TX power index table.");
|
||||
rtw8723x_debug_txpwr_limit(rtwdev,
|
||||
efuse->txpwr_idx_table, 2);
|
||||
}
|
||||
|
||||
/* Override invalid antenna settings. */
|
||||
if (efuse->bt_setting == 0xff) {
|
||||
/* shared antenna */
|
||||
efuse->bt_setting |= BIT(0);
|
||||
/* RF path A */
|
||||
efuse->bt_setting &= ~BIT(6);
|
||||
DBG_EFUSE_FIX(rtwdev, bt_setting);
|
||||
}
|
||||
|
||||
/* Override invalid board options: The coex code incorrectly
|
||||
* assumes that if bits 6 & 7 are set the board doesn't
|
||||
* support coex. Regd is also derived from rf_board_option and
|
||||
* should be 0 if there's no valid data.
|
||||
*/
|
||||
if (efuse->rf_board_option == 0xff) {
|
||||
efuse->regd = 0;
|
||||
efuse->rf_board_option &= GENMASK(5, 0);
|
||||
DBG_EFUSE_FIX(rtwdev, rf_board_option);
|
||||
}
|
||||
|
||||
/* Override invalid crystal cap setting, default comes from
|
||||
* vendor driver. Chip specific.
|
||||
*/
|
||||
if (efuse->crystal_cap == 0xff) {
|
||||
efuse->crystal_cap = 0x20;
|
||||
DBG_EFUSE_FIX(rtwdev, crystal_cap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1904,6 +1844,7 @@ static const struct rtw_chip_ops rtw8703b_ops = {
|
||||
.set_antenna = NULL,
|
||||
.cfg_ldo25 = rtw8723x_cfg_ldo25,
|
||||
.efuse_grant = rtw8723x_efuse_grant,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw8723x_false_alarm_statistics,
|
||||
.phy_calibration = rtw8703b_phy_calibration,
|
||||
.dpk_track = NULL,
|
||||
|
||||
@@ -19,7 +19,7 @@ static const struct sdio_device_id rtw_8723cs_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8723cs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8723cs_driver = {
|
||||
.name = "rtw8723cs",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8723cs_id_table,
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
|
||||
@@ -1404,6 +1404,7 @@ static const struct rtw_chip_ops rtw8723d_ops = {
|
||||
.set_antenna = NULL,
|
||||
.cfg_ldo25 = rtw8723x_cfg_ldo25,
|
||||
.efuse_grant = rtw8723x_efuse_grant,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw8723x_false_alarm_statistics,
|
||||
.phy_calibration = rtw8723d_phy_calibration,
|
||||
.cck_pd_set = rtw8723d_phy_cck_pd_set,
|
||||
|
||||
@@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8723de_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, rtw_8723de_id_table);
|
||||
|
||||
static struct pci_driver rtw_8723de_driver = {
|
||||
.name = "rtw_8723de",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8723de_id_table,
|
||||
.probe = rtw_pci_probe,
|
||||
.remove = rtw_pci_remove,
|
||||
|
||||
@@ -25,7 +25,7 @@ static const struct sdio_device_id rtw_8723ds_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8723ds_driver = {
|
||||
.name = "rtw_8723ds",
|
||||
.name = KBUILD_MODNAME,
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8723ds_id_table,
|
||||
|
||||
@@ -24,7 +24,7 @@ static int rtw8723du_probe(struct usb_interface *intf,
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8723du_driver = {
|
||||
.name = "rtw_8723du",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8723du_id_table,
|
||||
.probe = rtw8723du_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -69,6 +69,9 @@ static void __rtw8723x_lck(struct rtw_dev *rtwdev)
|
||||
#define DBG_EFUSE_2BYTE(rtwdev, map, name) \
|
||||
rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x%02x\n", \
|
||||
(map)->name[0], (map)->name[1])
|
||||
#define DBG_EFUSE_FIX(rtwdev, name) \
|
||||
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Fixed invalid EFUSE value: " \
|
||||
# name "=0x%x\n", rtwdev->efuse.name)
|
||||
|
||||
static void rtw8723xe_efuse_debug(struct rtw_dev *rtwdev,
|
||||
struct rtw8723x_efuse *map)
|
||||
@@ -238,10 +241,21 @@ static void rtw8723xs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
/* Default power index table for RTL8703B/RTL8723D, used if EFUSE does
|
||||
* not contain valid data. Replaces EFUSE data from offset 0x10 (start
|
||||
* of txpwr_idx_table).
|
||||
*/
|
||||
static const u8 rtw8723x_txpwr_idx_table[] = {
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
|
||||
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02
|
||||
};
|
||||
|
||||
static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u8 *pwr = (u8 *)efuse->txpwr_idx_table;
|
||||
struct rtw8723x_efuse *map;
|
||||
bool valid = false;
|
||||
int i;
|
||||
|
||||
map = (struct rtw8723x_efuse *)log_map;
|
||||
@@ -279,6 +293,51 @@ static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* If TX power index table in EFUSE is invalid, fall back to
|
||||
* built-in table.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++)
|
||||
if (pwr[i] != 0xff) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
if (!valid) {
|
||||
for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++)
|
||||
pwr[i] = rtw8723x_txpwr_idx_table[i];
|
||||
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
|
||||
"Replaced invalid EFUSE TX power index table.");
|
||||
rtw8723x_debug_txpwr_limit(rtwdev,
|
||||
efuse->txpwr_idx_table, 2);
|
||||
}
|
||||
|
||||
/* Override invalid antenna settings. */
|
||||
if (efuse->bt_setting == 0xff) {
|
||||
/* shared antenna */
|
||||
efuse->bt_setting |= BIT(0);
|
||||
/* RF path A */
|
||||
efuse->bt_setting &= ~BIT(6);
|
||||
DBG_EFUSE_FIX(rtwdev, bt_setting);
|
||||
}
|
||||
|
||||
/* Override invalid board options: The coex code incorrectly
|
||||
* assumes that if bits 6 & 7 are set the board doesn't
|
||||
* support coex. Regd is also derived from rf_board_option and
|
||||
* should be 0 if there's no valid data.
|
||||
*/
|
||||
if (efuse->rf_board_option == 0xff) {
|
||||
efuse->regd = 0;
|
||||
efuse->rf_board_option &= GENMASK(5, 0);
|
||||
DBG_EFUSE_FIX(rtwdev, rf_board_option);
|
||||
}
|
||||
|
||||
/* Override invalid crystal cap setting, default comes from
|
||||
* vendor driver. Chip specific.
|
||||
*/
|
||||
if (efuse->crystal_cap == 0xff) {
|
||||
efuse->crystal_cap = 0x20;
|
||||
DBG_EFUSE_FIX(rtwdev, crystal_cap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -925,6 +925,7 @@ static const struct rtw_chip_ops rtw8812a_ops = {
|
||||
.set_tx_power_index = rtw88xxa_set_tx_power_index,
|
||||
.cfg_ldo25 = rtw8812a_cfg_ldo25,
|
||||
.efuse_grant = rtw88xxa_efuse_grant,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw88xxa_false_alarm_statistics,
|
||||
.phy_calibration = rtw8812a_phy_calibration,
|
||||
.cck_pd_set = rtw88xxa_phy_cck_pd_set,
|
||||
@@ -1075,6 +1076,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = {
|
||||
.rfe_defs = rtw8812a_rfe_defs,
|
||||
.rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs),
|
||||
.rx_ldpc = false,
|
||||
.amsdu_in_ampdu = true,
|
||||
.hw_feature_report = false,
|
||||
.c2h_ra_report_size = 4,
|
||||
.old_datarate_fb_limit = true,
|
||||
|
||||
@@ -82,7 +82,7 @@ static const struct usb_device_id rtw_8812au_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table);
|
||||
|
||||
static struct usb_driver rtw_8812au_driver = {
|
||||
.name = "rtw_8812au",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8812au_id_table,
|
||||
.probe = rtw_usb_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -1332,6 +1332,16 @@ static void rtw8814a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
/* Without this RTL8814A sends too many frames and (some?) 11n AP
|
||||
* can't handle it, resulting in low TX speed. Other chips seem fine.
|
||||
*/
|
||||
static void rtw8814a_set_ampdu_factor(struct rtw_dev *rtwdev, u8 factor)
|
||||
{
|
||||
factor = min_t(u8, factor, IEEE80211_VHT_MAX_AMPDU_256K);
|
||||
|
||||
rtw_write32(rtwdev, REG_AMPDU_MAX_LENGTH, (8192 << factor) - 1);
|
||||
}
|
||||
|
||||
static void rtw8814a_false_alarm_statistics(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
@@ -2051,6 +2061,7 @@ static const struct rtw_chip_ops rtw8814a_ops = {
|
||||
.set_antenna = NULL,
|
||||
.cfg_ldo25 = rtw8814a_cfg_ldo25,
|
||||
.efuse_grant = rtw8814a_efuse_grant,
|
||||
.set_ampdu_factor = rtw8814a_set_ampdu_factor,
|
||||
.false_alarm_statistics = rtw8814a_false_alarm_statistics,
|
||||
.phy_calibration = rtw8814a_phy_calibration,
|
||||
.cck_pd_set = rtw8814a_phy_cck_pd_set,
|
||||
@@ -2189,6 +2200,7 @@ const struct rtw_chip_info rtw8814a_hw_spec = {
|
||||
.rx_ldpc = true,
|
||||
.max_power_index = 0x3f,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
|
||||
.amsdu_in_ampdu = false, /* RX speed is better without AMSDU */
|
||||
.usb_tx_agg_desc_num = 3,
|
||||
.hw_feature_report = false,
|
||||
.c2h_ra_report_size = 6,
|
||||
|
||||
@@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8814ae_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, rtw_8814ae_id_table);
|
||||
|
||||
static struct pci_driver rtw_8814ae_driver = {
|
||||
.name = "rtw_8814ae",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8814ae_id_table,
|
||||
.probe = rtw_pci_probe,
|
||||
.remove = rtw_pci_remove,
|
||||
|
||||
@@ -42,7 +42,7 @@ static const struct usb_device_id rtw_8814au_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8814au_id_table);
|
||||
|
||||
static struct usb_driver rtw_8814au_driver = {
|
||||
.name = "rtw_8814au",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8814au_id_table,
|
||||
.probe = rtw_usb_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -871,6 +871,7 @@ static const struct rtw_chip_ops rtw8821a_ops = {
|
||||
.set_tx_power_index = rtw88xxa_set_tx_power_index,
|
||||
.cfg_ldo25 = rtw8821a_cfg_ldo25,
|
||||
.efuse_grant = rtw88xxa_efuse_grant,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw88xxa_false_alarm_statistics,
|
||||
.phy_calibration = rtw8821a_phy_calibration,
|
||||
.cck_pd_set = rtw88xxa_phy_cck_pd_set,
|
||||
@@ -1175,6 +1176,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = {
|
||||
.rfe_defs = rtw8821a_rfe_defs,
|
||||
.rfe_defs_size = ARRAY_SIZE(rtw8821a_rfe_defs),
|
||||
.rx_ldpc = false,
|
||||
.amsdu_in_ampdu = true,
|
||||
.hw_feature_report = false,
|
||||
.c2h_ra_report_size = 4,
|
||||
.old_datarate_fb_limit = true,
|
||||
|
||||
@@ -66,7 +66,7 @@ static const struct usb_device_id rtw_8821au_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table);
|
||||
|
||||
static struct usb_driver rtw_8821au_driver = {
|
||||
.name = "rtw_8821au",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8821au_id_table,
|
||||
.probe = rtw_usb_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -1668,6 +1668,7 @@ static const struct rtw_chip_ops rtw8821c_ops = {
|
||||
.set_antenna = NULL,
|
||||
.set_tx_power_index = rtw8821c_set_tx_power_index,
|
||||
.cfg_ldo25 = rtw8821c_cfg_ldo25,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw8821c_false_alarm_statistics,
|
||||
.phy_calibration = rtw8821c_phy_calibration,
|
||||
.cck_pd_set = rtw8821c_phy_cck_pd_set,
|
||||
@@ -1990,6 +1991,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x1c,
|
||||
.amsdu_in_ampdu = true,
|
||||
.usb_tx_agg_desc_num = 3,
|
||||
.hw_feature_report = true,
|
||||
.c2h_ra_report_size = 7,
|
||||
|
||||
@@ -21,7 +21,7 @@ static const struct pci_device_id rtw_8821ce_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, rtw_8821ce_id_table);
|
||||
|
||||
static struct pci_driver rtw_8821ce_driver = {
|
||||
.name = "rtw_8821ce",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8821ce_id_table,
|
||||
.probe = rtw_pci_probe,
|
||||
.remove = rtw_pci_remove,
|
||||
|
||||
@@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8821cs_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8821cs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8821cs_driver = {
|
||||
.name = "rtw_8821cs",
|
||||
.name = KBUILD_MODNAME,
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8821cs_id_table,
|
||||
|
||||
@@ -48,7 +48,7 @@ static int rtw_8821cu_probe(struct usb_interface *intf,
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8821cu_driver = {
|
||||
.name = "rtw_8821cu",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8821cu_id_table,
|
||||
.probe = rtw_8821cu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -2158,6 +2158,7 @@ static const struct rtw_chip_ops rtw8822b_ops = {
|
||||
.set_tx_power_index = rtw8822b_set_tx_power_index,
|
||||
.set_antenna = rtw8822b_set_antenna,
|
||||
.cfg_ldo25 = rtw8822b_cfg_ldo25,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw8822b_false_alarm_statistics,
|
||||
.phy_calibration = rtw8822b_phy_calibration,
|
||||
.pwr_track = rtw8822b_pwr_track,
|
||||
@@ -2531,6 +2532,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x1c,
|
||||
.amsdu_in_ampdu = true,
|
||||
.usb_tx_agg_desc_num = 3,
|
||||
.hw_feature_report = true,
|
||||
.c2h_ra_report_size = 7,
|
||||
|
||||
@@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8822be_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, rtw_8822be_id_table);
|
||||
|
||||
static struct pci_driver rtw_8822be_driver = {
|
||||
.name = "rtw_8822be",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8822be_id_table,
|
||||
.probe = rtw_pci_probe,
|
||||
.remove = rtw_pci_remove,
|
||||
|
||||
@@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8822bs_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8822bs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8822bs_driver = {
|
||||
.name = "rtw_8822bs",
|
||||
.name = KBUILD_MODNAME,
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8822bs_id_table,
|
||||
|
||||
@@ -77,6 +77,8 @@ static const struct usb_device_id rtw_8822bu_id_table[] = {
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30N */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3322, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* D-Link DWA-T185 rev. A1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03d1, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* BUFFALO WI-U2-866DM */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);
|
||||
@@ -88,7 +90,7 @@ static int rtw8822bu_probe(struct usb_interface *intf,
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822bu_driver = {
|
||||
.name = "rtw_8822bu",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8822bu_id_table,
|
||||
.probe = rtw8822bu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -3951,7 +3951,8 @@ static void rtw8822c_dpk_cal_coef1(struct rtw_dev *rtwdev)
|
||||
rtw_write32(rtwdev, REG_NCTL0, 0x00001148);
|
||||
rtw_write32(rtwdev, REG_NCTL0, 0x00001149);
|
||||
|
||||
check_hw_ready(rtwdev, 0x2d9c, MASKBYTE0, 0x55);
|
||||
if (!check_hw_ready(rtwdev, 0x2d9c, MASKBYTE0, 0x55))
|
||||
rtw_warn(rtwdev, "DPK stuck, performance may be suboptimal");
|
||||
|
||||
rtw_write8(rtwdev, 0x1b10, 0x0);
|
||||
rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SUBPAGE, 0x0000000c);
|
||||
@@ -4968,6 +4969,7 @@ static const struct rtw_chip_ops rtw8822c_ops = {
|
||||
.set_tx_power_index = rtw8822c_set_tx_power_index,
|
||||
.set_antenna = rtw8822c_set_antenna,
|
||||
.cfg_ldo25 = rtw8822c_cfg_ldo25,
|
||||
.set_ampdu_factor = NULL,
|
||||
.false_alarm_statistics = rtw8822c_false_alarm_statistics,
|
||||
.dpk_track = rtw8822c_dpk_track,
|
||||
.phy_calibration = rtw8822c_phy_calibration,
|
||||
@@ -5349,6 +5351,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x20,
|
||||
.amsdu_in_ampdu = true,
|
||||
.usb_tx_agg_desc_num = 3,
|
||||
.hw_feature_report = true,
|
||||
.c2h_ra_report_size = 7,
|
||||
|
||||
@@ -21,7 +21,7 @@ static const struct pci_device_id rtw_8822ce_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, rtw_8822ce_id_table);
|
||||
|
||||
static struct pci_driver rtw_8822ce_driver = {
|
||||
.name = "rtw_8822ce",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8822ce_id_table,
|
||||
.probe = rtw_pci_probe,
|
||||
.remove = rtw_pci_remove,
|
||||
|
||||
@@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8822cs_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8822cs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8822cs_driver = {
|
||||
.name = "rtw_8822cs",
|
||||
.name = KBUILD_MODNAME,
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8822cs_id_table,
|
||||
|
||||
@@ -32,7 +32,7 @@ static int rtw8822cu_probe(struct usb_interface *intf,
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822cu_driver = {
|
||||
.name = "rtw_8822cu",
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rtw_8822cu_id_table,
|
||||
.probe = rtw8822cu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include "main.h"
|
||||
#include "mac.h"
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "ps.h"
|
||||
@@ -677,12 +678,22 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)
|
||||
{
|
||||
u8 size, timeout;
|
||||
|
||||
if (rtw_chip_wcpu_11n(rtwdev)) {
|
||||
switch (rtwdev->chip->id) {
|
||||
case RTW_CHIP_TYPE_8703B:
|
||||
case RTW_CHIP_TYPE_8821A:
|
||||
case RTW_CHIP_TYPE_8812A:
|
||||
size = 0x6;
|
||||
timeout = 0x6;
|
||||
} else {
|
||||
break;
|
||||
case RTW_CHIP_TYPE_8723D:
|
||||
size = 0xa;
|
||||
timeout = 0x3;
|
||||
rtw_write8_set(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7));
|
||||
break;
|
||||
default:
|
||||
size = 0xff;
|
||||
timeout = 0x1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make the firmware honor the size limit configured below */
|
||||
@@ -718,10 +729,7 @@ static u8 rtw_sdio_get_tx_qsel(struct rtw_dev *rtwdev, struct sk_buff *skb,
|
||||
case RTW_TX_QUEUE_H2C:
|
||||
return TX_DESC_QSEL_H2C;
|
||||
case RTW_TX_QUEUE_MGMT:
|
||||
if (rtw_chip_wcpu_11n(rtwdev))
|
||||
return TX_DESC_QSEL_HIGH;
|
||||
else
|
||||
return TX_DESC_QSEL_MGMT;
|
||||
return TX_DESC_QSEL_MGMT;
|
||||
case RTW_TX_QUEUE_HI0:
|
||||
return TX_DESC_QSEL_HIGH;
|
||||
default:
|
||||
@@ -1157,6 +1165,7 @@ static const struct rtw_hci_ops rtw_sdio_ops = {
|
||||
.link_ps = rtw_sdio_link_ps,
|
||||
.interface_cfg = rtw_sdio_interface_cfg,
|
||||
.dynamic_rx_agg = NULL,
|
||||
.write_firmware_page = rtw_write_firmware_page,
|
||||
|
||||
.read8 = rtw_sdio_read8,
|
||||
.read16 = rtw_sdio_read16,
|
||||
@@ -1227,10 +1236,7 @@ static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,
|
||||
return;
|
||||
}
|
||||
|
||||
if (queue <= RTW_TX_QUEUE_VO)
|
||||
rtw_sdio_indicate_tx_status(rtwdev, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
rtw_sdio_indicate_tx_status(rtwdev, skb);
|
||||
}
|
||||
|
||||
static void rtw_sdio_tx_handler(struct work_struct *work)
|
||||
@@ -1298,7 +1304,6 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)
|
||||
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
|
||||
int i;
|
||||
|
||||
flush_workqueue(rtwsdio->txwq);
|
||||
destroy_workqueue(rtwsdio->txwq);
|
||||
kfree(rtwsdio->tx_handler_data);
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
||||
addr, 0, data, len, 30000);
|
||||
addr, 0, data, len, 500);
|
||||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
@@ -165,6 +165,60 @@ static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
|
||||
rtw_usb_write(rtwdev, addr, val, 4);
|
||||
}
|
||||
|
||||
static void rtw_usb_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
|
||||
const u8 *data, u32 size)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
u32 addr = FW_START_ADDR_LEGACY;
|
||||
u8 *data_dup, *buf;
|
||||
u32 n, block_size;
|
||||
int ret;
|
||||
|
||||
switch (rtwdev->chip->id) {
|
||||
case RTW_CHIP_TYPE_8723D:
|
||||
block_size = 254;
|
||||
break;
|
||||
default:
|
||||
block_size = 196;
|
||||
break;
|
||||
}
|
||||
|
||||
data_dup = kmemdup(data, size, GFP_KERNEL);
|
||||
if (!data_dup)
|
||||
return;
|
||||
|
||||
buf = data_dup;
|
||||
|
||||
rtw_write32_mask(rtwdev, REG_MCUFW_CTRL, BIT_ROM_PGE, page);
|
||||
|
||||
while (size > 0) {
|
||||
if (size >= block_size)
|
||||
n = block_size;
|
||||
else if (size >= 8)
|
||||
n = 8;
|
||||
else
|
||||
n = 1;
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
||||
addr, 0, buf, n, 500);
|
||||
if (ret != n) {
|
||||
if (ret != -ENODEV)
|
||||
rtw_err(rtwdev,
|
||||
"write 0x%x len %d failed: %d\n",
|
||||
addr, n, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
addr += n;
|
||||
buf += n;
|
||||
size -= n;
|
||||
}
|
||||
|
||||
kfree(data_dup);
|
||||
}
|
||||
|
||||
static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)
|
||||
{
|
||||
switch (dma_mapping) {
|
||||
@@ -866,6 +920,7 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
|
||||
case RTW_CHIP_TYPE_8822C:
|
||||
case RTW_CHIP_TYPE_8822B:
|
||||
case RTW_CHIP_TYPE_8821C:
|
||||
case RTW_CHIP_TYPE_8814A:
|
||||
rtw_usb_dynamic_rx_agg_v1(rtwdev, enable);
|
||||
break;
|
||||
case RTW_CHIP_TYPE_8821A:
|
||||
@@ -891,6 +946,7 @@ static const struct rtw_hci_ops rtw_usb_ops = {
|
||||
.link_ps = rtw_usb_link_ps,
|
||||
.interface_cfg = rtw_usb_interface_cfg,
|
||||
.dynamic_rx_agg = rtw_usb_dynamic_rx_agg,
|
||||
.write_firmware_page = rtw_usb_write_firmware_page,
|
||||
|
||||
.write8 = rtw_usb_write8,
|
||||
.write16 = rtw_usb_write16,
|
||||
@@ -948,7 +1004,6 @@ static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
|
||||
|
||||
skb_queue_purge(&rtwusb->rx_queue);
|
||||
|
||||
flush_workqueue(rtwusb->rxwq);
|
||||
destroy_workqueue(rtwusb->rxwq);
|
||||
|
||||
skb_queue_purge(&rtwusb->rx_free_queue);
|
||||
@@ -977,7 +1032,6 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
flush_workqueue(rtwusb->txwq);
|
||||
destroy_workqueue(rtwusb->txwq);
|
||||
rtw_usb_tx_queue_purge(rtwusb);
|
||||
}
|
||||
@@ -1094,7 +1148,8 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
|
||||
|
||||
static bool rtw_usb3_chip_old(u8 chip_id)
|
||||
{
|
||||
return chip_id == RTW_CHIP_TYPE_8812A;
|
||||
return chip_id == RTW_CHIP_TYPE_8812A ||
|
||||
chip_id == RTW_CHIP_TYPE_8814A;
|
||||
}
|
||||
|
||||
static bool rtw_usb3_chip_new(u8 chip_id)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,11 @@
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct rtw89_acpi_data {
|
||||
u32 len;
|
||||
u8 buf[] __counted_by(len);
|
||||
};
|
||||
|
||||
enum rtw89_acpi_dsm_func {
|
||||
RTW89_ACPI_DSM_FUNC_IDN_BAND_SUP = 2,
|
||||
RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
|
||||
@@ -26,6 +31,13 @@ enum rtw89_acpi_policy_mode {
|
||||
RTW89_ACPI_POLICY_ALLOW = 1,
|
||||
};
|
||||
|
||||
enum rtw89_acpi_conf_tas {
|
||||
RTW89_ACPI_CONF_TAS_US = BIT(0),
|
||||
RTW89_ACPI_CONF_TAS_CA = BIT(1),
|
||||
RTW89_ACPI_CONF_TAS_KR = BIT(2),
|
||||
RTW89_ACPI_CONF_TAS_OTHERS = BIT(7),
|
||||
};
|
||||
|
||||
struct rtw89_acpi_country_code {
|
||||
/* below are allowed:
|
||||
* * ISO alpha2 country code
|
||||
@@ -54,12 +66,21 @@ struct rtw89_acpi_policy_6ghz_sp {
|
||||
u8 rsvd;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_policy_tas {
|
||||
u8 signature[4];
|
||||
u8 revision;
|
||||
u8 enable;
|
||||
u8 enabled_countries;
|
||||
u8 rsvd[3];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_dsm_result {
|
||||
union {
|
||||
u8 value;
|
||||
/* caller needs to free it after using */
|
||||
struct rtw89_acpi_policy_6ghz *policy_6ghz;
|
||||
struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp;
|
||||
struct rtw89_acpi_policy_tas *policy_tas;
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -70,10 +91,179 @@ struct rtw89_acpi_rtag_result {
|
||||
u8 ant_gain_table[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR];
|
||||
} __packed;
|
||||
|
||||
enum rtw89_acpi_sar_cid {
|
||||
RTW89_ACPI_SAR_CID_HP = 0x5048,
|
||||
RTW89_ACPI_SAR_CID_RT = 0x5452,
|
||||
};
|
||||
|
||||
enum rtw89_acpi_sar_rev {
|
||||
RTW89_ACPI_SAR_REV_LEGACY = 1,
|
||||
RTW89_ACPI_SAR_REV_HAS_6GHZ = 2,
|
||||
};
|
||||
|
||||
#define RTW89_ACPI_SAR_ANT_NR_STD 4
|
||||
#define RTW89_ACPI_SAR_ANT_NR_SML 2
|
||||
|
||||
#define RTW89_ACPI_METHOD_STATIC_SAR "WRDS"
|
||||
#define RTW89_ACPI_METHOD_DYNAMIC_SAR "RWRD"
|
||||
#define RTW89_ACPI_METHOD_DYNAMIC_SAR_INDICATOR "RWSI"
|
||||
#define RTW89_ACPI_METHOD_GEO_SAR "RWGS"
|
||||
|
||||
struct rtw89_acpi_sar_std_legacy {
|
||||
u8 v[RTW89_ACPI_SAR_ANT_NR_STD][RTW89_ACPI_SAR_SUBBAND_NR_LEGACY];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_sar_std_has_6ghz {
|
||||
u8 v[RTW89_ACPI_SAR_ANT_NR_STD][RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_sar_sml_legacy {
|
||||
u8 v[RTW89_ACPI_SAR_ANT_NR_SML][RTW89_ACPI_SAR_SUBBAND_NR_LEGACY];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_sar_sml_has_6ghz {
|
||||
u8 v[RTW89_ACPI_SAR_ANT_NR_SML][RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_static_sar_hdr {
|
||||
__le16 cid;
|
||||
u8 rev;
|
||||
u8 content[];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_dynamic_sar_hdr {
|
||||
__le16 cid;
|
||||
u8 rev;
|
||||
u8 cnt;
|
||||
u8 content[];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_sar_identifier {
|
||||
enum rtw89_acpi_sar_cid cid;
|
||||
enum rtw89_acpi_sar_rev rev;
|
||||
u8 size;
|
||||
};
|
||||
|
||||
/* for rtw89_acpi_sar_identifier::size */
|
||||
#define RTW89_ACPI_SAR_SIZE_MAX U8_MAX
|
||||
#define RTW89_ACPI_SAR_SIZE_OF(type) \
|
||||
(BUILD_BUG_ON_ZERO(sizeof(struct rtw89_acpi_sar_ ## type) > \
|
||||
RTW89_ACPI_SAR_SIZE_MAX) + \
|
||||
sizeof(struct rtw89_acpi_sar_ ## type))
|
||||
|
||||
struct rtw89_acpi_sar_recognition {
|
||||
struct rtw89_acpi_sar_identifier id;
|
||||
const struct rtw89_acpi_geo_sar_handler *geo;
|
||||
|
||||
u8 (*rfpath_to_antidx)(enum rtw89_rf_path rfpath);
|
||||
s16 (*normalize)(u8 v);
|
||||
void (*load)(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_acpi_sar_recognition *rec,
|
||||
const void *content,
|
||||
struct rtw89_sar_entry_from_acpi *ent);
|
||||
};
|
||||
|
||||
struct rtw89_acpi_geo_sar_hp_val {
|
||||
u8 max;
|
||||
s8 delta[RTW89_ACPI_SAR_ANT_NR_STD];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_hp_legacy_entry {
|
||||
struct rtw89_acpi_geo_sar_hp_val val_2ghz;
|
||||
struct rtw89_acpi_geo_sar_hp_val val_5ghz;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_hp_has_6ghz_entry {
|
||||
struct rtw89_acpi_geo_sar_hp_val val_2ghz;
|
||||
struct rtw89_acpi_geo_sar_hp_val val_5ghz;
|
||||
struct rtw89_acpi_geo_sar_hp_val val_6ghz;
|
||||
} __packed;
|
||||
|
||||
enum rtw89_acpi_geo_sar_regd_hp {
|
||||
RTW89_ACPI_GEO_SAR_REGD_HP_FCC = 0,
|
||||
RTW89_ACPI_GEO_SAR_REGD_HP_ETSI = 1,
|
||||
RTW89_ACPI_GEO_SAR_REGD_HP_WW = 2,
|
||||
|
||||
RTW89_ACPI_GEO_SAR_REGD_NR_HP,
|
||||
};
|
||||
|
||||
struct rtw89_acpi_geo_sar_hp_legacy {
|
||||
struct rtw89_acpi_geo_sar_hp_legacy_entry
|
||||
entries[RTW89_ACPI_GEO_SAR_REGD_NR_HP];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_hp_has_6ghz {
|
||||
struct rtw89_acpi_geo_sar_hp_has_6ghz_entry
|
||||
entries[RTW89_ACPI_GEO_SAR_REGD_NR_HP];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_rt_val {
|
||||
u8 max;
|
||||
s8 delta;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_rt_legacy_entry {
|
||||
struct rtw89_acpi_geo_sar_rt_val val_2ghz;
|
||||
struct rtw89_acpi_geo_sar_rt_val val_5ghz;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_rt_has_6ghz_entry {
|
||||
struct rtw89_acpi_geo_sar_rt_val val_2ghz;
|
||||
struct rtw89_acpi_geo_sar_rt_val val_5ghz;
|
||||
struct rtw89_acpi_geo_sar_rt_val val_6ghz;
|
||||
} __packed;
|
||||
|
||||
enum rtw89_acpi_geo_sar_regd_rt {
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_FCC = 0,
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_ETSI = 1,
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_MKK = 2,
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_IC = 3,
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_KCC = 4,
|
||||
RTW89_ACPI_GEO_SAR_REGD_RT_WW = 5,
|
||||
|
||||
RTW89_ACPI_GEO_SAR_REGD_NR_RT,
|
||||
};
|
||||
|
||||
struct rtw89_acpi_geo_sar_rt_legacy {
|
||||
struct rtw89_acpi_geo_sar_rt_legacy_entry
|
||||
entries[RTW89_ACPI_GEO_SAR_REGD_NR_RT];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_rt_has_6ghz {
|
||||
struct rtw89_acpi_geo_sar_rt_has_6ghz_entry
|
||||
entries[RTW89_ACPI_GEO_SAR_REGD_NR_RT];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_geo_sar_handler {
|
||||
u8 data_size;
|
||||
|
||||
void (*load)(struct rtw89_dev *rtwdev,
|
||||
const void *content,
|
||||
enum rtw89_regulation_type regd,
|
||||
struct rtw89_sar_entry_from_acpi *ent);
|
||||
};
|
||||
|
||||
/* for rtw89_acpi_geo_sar_handler::data_size */
|
||||
#define RTW89_ACPI_GEO_SAR_SIZE_MAX U8_MAX
|
||||
#define RTW89_ACPI_GEO_SAR_SIZE_OF(type) \
|
||||
(BUILD_BUG_ON_ZERO(sizeof(struct rtw89_acpi_geo_sar_ ## type) > \
|
||||
RTW89_ACPI_GEO_SAR_SIZE_MAX) + \
|
||||
sizeof(struct rtw89_acpi_geo_sar_ ## type))
|
||||
|
||||
enum rtw89_acpi_sar_subband rtw89_acpi_sar_get_subband(struct rtw89_dev *rtwdev,
|
||||
u32 center_freq);
|
||||
enum rtw89_band rtw89_acpi_sar_subband_to_band(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_acpi_sar_subband subband);
|
||||
|
||||
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);
|
||||
int rtw89_acpi_evaluate_sar(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sar_cfg_acpi *cfg);
|
||||
int rtw89_acpi_evaluate_dynamic_sar_indicator(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sar_cfg_acpi *cfg,
|
||||
bool *changed);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
#include "ps.h"
|
||||
|
||||
static struct sk_buff *
|
||||
rtw89_cam_get_sec_key_cmd(struct rtw89_dev *rtwdev,
|
||||
@@ -469,11 +470,17 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
|
||||
bool ext_key = false;
|
||||
int ret;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif) && !chip->hw_mlo_bmc_crypto &&
|
||||
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
hw_key_type = RTW89_SEC_KEY_TYPE_WEP40;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
hw_key_type = RTW89_SEC_KEY_TYPE_WEP104;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
|
||||
@@ -189,9 +189,10 @@ void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_idx idx,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
enum rtw89_chanctx_idx cur;
|
||||
|
||||
@@ -205,6 +206,7 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
hal->roc_chandef = *chandef;
|
||||
hal->roc_link_index = rtw89_vif_link_inst_get_index(rtwvif_link);
|
||||
} else {
|
||||
cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx,
|
||||
RTW89_CHANCTX_IDLE);
|
||||
@@ -339,11 +341,10 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
|
||||
|
||||
roc_idx = atomic_read(&hal->roc_chanctx_idx);
|
||||
if (roc_idx != RTW89_CHANCTX_IDLE) {
|
||||
/* ROC is ongoing (given ROC runs on RTW89_ROC_BY_LINK_INDEX).
|
||||
* If @link_index is the same as RTW89_ROC_BY_LINK_INDEX, get
|
||||
* the ongoing ROC chanctx.
|
||||
/* ROC is ongoing (given ROC runs on @hal->roc_link_index).
|
||||
* If @link_index is the same, get the ongoing ROC chanctx.
|
||||
*/
|
||||
if (link_index == RTW89_ROC_BY_LINK_INDEX)
|
||||
if (link_index == hal->roc_link_index)
|
||||
chanctx_idx = roc_idx;
|
||||
}
|
||||
|
||||
@@ -358,12 +359,41 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
|
||||
|
||||
static enum rtw89_mlo_dbcc_mode
|
||||
rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
|
||||
{
|
||||
if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
|
||||
return MLO_DBCC_NOT_SUPPORT;
|
||||
|
||||
switch (active_hws) {
|
||||
case BIT(0):
|
||||
return MLO_2_PLUS_0_1RF;
|
||||
case BIT(1):
|
||||
return MLO_0_PLUS_2_1RF;
|
||||
case BIT(0) | BIT(1):
|
||||
default:
|
||||
return MLO_1_PLUS_1_1RF;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
|
||||
{
|
||||
enum rtw89_mlo_dbcc_mode mode;
|
||||
|
||||
mode = rtw89_entity_sel_mlo_dbcc_mode(rtwdev, active_hws);
|
||||
rtwdev->mlo_dbcc_mode = mode;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_STATE, "recalc mlo dbcc mode to %d\n", mode);
|
||||
}
|
||||
|
||||
static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
|
||||
struct rtw89_vif_link *link;
|
||||
struct rtw89_vif *role;
|
||||
u8 active_hws = 0;
|
||||
u8 pos = 0;
|
||||
int i, j;
|
||||
|
||||
@@ -412,10 +442,13 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
|
||||
continue;
|
||||
|
||||
mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
|
||||
active_hws |= BIT(i);
|
||||
}
|
||||
|
||||
mgnt->active_roles[pos++] = role;
|
||||
}
|
||||
|
||||
rtw89_entity_recalc_mlo_dbcc_mode(rtwdev, active_hws);
|
||||
}
|
||||
|
||||
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
|
||||
@@ -557,7 +590,9 @@ static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
|
||||
u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
|
||||
u32 remainder;
|
||||
|
||||
if (tsf < sync_tsf) {
|
||||
if (role->is_go) {
|
||||
sync_tsf = 0;
|
||||
} else if (tsf < sync_tsf) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC get tbtt ofst: tsf might not update yet\n");
|
||||
sync_tsf = 0;
|
||||
@@ -691,19 +726,13 @@ static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
|
||||
struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
|
||||
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
|
||||
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
|
||||
struct rtw89_sta_link *rtwsta_link;
|
||||
u8 macid;
|
||||
|
||||
if (rtwvif != target)
|
||||
return;
|
||||
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
if (unlikely(!rtwsta_link)) {
|
||||
rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id);
|
||||
macid = rtw89_sta_get_main_macid(rtwsta);
|
||||
rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, macid);
|
||||
}
|
||||
|
||||
static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev,
|
||||
@@ -747,9 +776,11 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!mcc_role->is_go && !mcc_role->is_gc)
|
||||
if (!mcc_role->is_gc)
|
||||
return;
|
||||
|
||||
rtw89_p2p_noa_once_recalc(rtwvif_link);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
|
||||
@@ -785,6 +816,9 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
tsf_lmt = (tsf & GENMASK_ULL(63, 32)) | start_time;
|
||||
if (tsf_lmt < tsf)
|
||||
tsf_lmt += roundup_u64(tsf - tsf_lmt, interval);
|
||||
|
||||
max_toa_us = rtw89_mcc_get_tbtt_ofst(rtwdev, mcc_role, tsf_lmt);
|
||||
max_dur_us = interval - duration;
|
||||
max_tob_us = max_dur_us - max_toa_us;
|
||||
@@ -929,6 +963,15 @@ static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool rtw89_mcc_can_courtesy(const struct rtw89_mcc_role *provider,
|
||||
const struct rtw89_mcc_role *receiver)
|
||||
{
|
||||
if (provider->is_go || receiver->is_gc)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_mcc_pattern *new)
|
||||
{
|
||||
@@ -937,37 +980,44 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_pattern *pattern = &config->pattern;
|
||||
struct rtw89_mcc_courtesy_cfg *crtz;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC assign pattern: ref {%d | %d}, aux {%d | %d}\n",
|
||||
new->tob_ref, new->toa_ref, new->tob_aux, new->toa_aux);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC pattern plan: %d\n", new->plan);
|
||||
|
||||
*pattern = *new;
|
||||
memset(&pattern->courtesy, 0, sizeof(pattern->courtesy));
|
||||
|
||||
if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) {
|
||||
pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id;
|
||||
pattern->courtesy.macid_src = ref->rtwvif_link->mac_id;
|
||||
pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
|
||||
pattern->courtesy.enable = true;
|
||||
} else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) {
|
||||
pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id;
|
||||
pattern->courtesy.macid_src = aux->rtwvif_link->mac_id;
|
||||
pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
|
||||
pattern->courtesy.enable = true;
|
||||
if (RTW89_MCC_REQ_COURTESY(pattern, aux) && rtw89_mcc_can_courtesy(ref, aux)) {
|
||||
crtz = &pattern->courtesy.ref;
|
||||
ref->crtz = crtz;
|
||||
|
||||
crtz->macid_tgt = aux->rtwvif_link->mac_id;
|
||||
crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC courtesy ref: tgt %d, slot %d\n",
|
||||
crtz->macid_tgt, crtz->slot_num);
|
||||
} else {
|
||||
ref->crtz = NULL;
|
||||
}
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC pattern flags: plan %d, courtesy_en %d\n",
|
||||
pattern->plan, pattern->courtesy.enable);
|
||||
if (RTW89_MCC_REQ_COURTESY(pattern, ref) && rtw89_mcc_can_courtesy(aux, ref)) {
|
||||
crtz = &pattern->courtesy.aux;
|
||||
aux->crtz = crtz;
|
||||
|
||||
if (!pattern->courtesy.enable)
|
||||
return;
|
||||
crtz->macid_tgt = ref->rtwvif_link->mac_id;
|
||||
crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC pattern courtesy: tgt %d, src %d, slot %d\n",
|
||||
pattern->courtesy.macid_tgt, pattern->courtesy.macid_src,
|
||||
pattern->courtesy.slot_num);
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC courtesy aux: tgt %d, slot %d\n",
|
||||
crtz->macid_tgt, crtz->slot_num);
|
||||
} else {
|
||||
aux->crtz = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* The follow-up roughly shows the relationship between the parameters
|
||||
@@ -992,6 +1042,7 @@ static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u16 mcc_intvl = config->mcc_interval;
|
||||
u16 bcn_ofst = config->beacon_offset;
|
||||
u16 bt_dur_in_mid = 0;
|
||||
u16 max_bcn_ofst;
|
||||
@@ -1025,7 +1076,7 @@ static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev,
|
||||
|
||||
res = bcn_ofst - bt_dur_in_mid;
|
||||
upper = min_t(s16, ref->duration, res);
|
||||
lower = 0;
|
||||
lower = max_t(s16, 0, ref->duration - (mcc_intvl - bcn_ofst));
|
||||
|
||||
if (ref->limit.enable) {
|
||||
upper = min_t(s16, upper, ref->limit.max_toa);
|
||||
@@ -1136,6 +1187,107 @@ static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __rtw89_mcc_fill_ptrn_anchor_ref(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_pattern *ptrn,
|
||||
bool small_bcn_ofst)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u16 bcn_ofst = config->beacon_offset;
|
||||
u16 ref_tob;
|
||||
u16 ref_toa;
|
||||
|
||||
if (ref->limit.enable) {
|
||||
ref_tob = ref->limit.max_tob;
|
||||
ref_toa = ref->limit.max_toa;
|
||||
} else {
|
||||
ref_tob = ref->duration / 2;
|
||||
ref_toa = ref->duration / 2;
|
||||
}
|
||||
|
||||
if (small_bcn_ofst) {
|
||||
ptrn->toa_ref = ref_toa;
|
||||
ptrn->tob_ref = ref->duration - ptrn->toa_ref;
|
||||
} else {
|
||||
ptrn->tob_ref = ref_tob;
|
||||
ptrn->toa_ref = ref->duration - ptrn->tob_ref;
|
||||
}
|
||||
|
||||
ptrn->tob_aux = bcn_ofst - ptrn->toa_ref;
|
||||
ptrn->toa_aux = aux->duration - ptrn->tob_aux;
|
||||
}
|
||||
|
||||
static void __rtw89_mcc_fill_ptrn_anchor_aux(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_pattern *ptrn,
|
||||
bool small_bcn_ofst)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u16 bcn_ofst = config->beacon_offset;
|
||||
u16 aux_tob;
|
||||
u16 aux_toa;
|
||||
|
||||
if (aux->limit.enable) {
|
||||
aux_tob = aux->limit.max_tob;
|
||||
aux_toa = aux->limit.max_toa;
|
||||
} else {
|
||||
aux_tob = aux->duration / 2;
|
||||
aux_toa = aux->duration / 2;
|
||||
}
|
||||
|
||||
if (small_bcn_ofst) {
|
||||
ptrn->tob_aux = aux_tob;
|
||||
ptrn->toa_aux = aux->duration - ptrn->tob_aux;
|
||||
} else {
|
||||
ptrn->toa_aux = aux_toa;
|
||||
ptrn->tob_aux = aux->duration - ptrn->toa_aux;
|
||||
}
|
||||
|
||||
ptrn->toa_ref = bcn_ofst - ptrn->tob_aux;
|
||||
ptrn->tob_ref = ref->duration - ptrn->toa_ref;
|
||||
}
|
||||
|
||||
static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_pattern *ptrn,
|
||||
bool hdl_bt)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u16 mcc_intvl = config->mcc_interval;
|
||||
u16 bcn_ofst = config->beacon_offset;
|
||||
bool small_bcn_ofst;
|
||||
|
||||
if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME)
|
||||
small_bcn_ofst = true;
|
||||
else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME)
|
||||
small_bcn_ofst = false;
|
||||
else
|
||||
return -EPERM;
|
||||
|
||||
*ptrn = (typeof(*ptrn)){
|
||||
.plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
|
||||
};
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC calc ptrn_ac: plan %d, bcn_ofst %d\n",
|
||||
ptrn->plan, bcn_ofst);
|
||||
|
||||
if (ref->is_go || ref->is_gc)
|
||||
__rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
|
||||
else if (aux->is_go || aux->is_gc)
|
||||
__rtw89_mcc_fill_ptrn_anchor_aux(rtwdev, ptrn, small_bcn_ofst);
|
||||
else
|
||||
__rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
@@ -1189,6 +1341,10 @@ static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = __rtw89_mcc_calc_pattern_anchor(rtwdev, &ptrn, hdl_bt);
|
||||
if (!ret)
|
||||
goto done;
|
||||
|
||||
__rtw89_mcc_calc_pattern_loose(rtwdev, &ptrn, hdl_bt);
|
||||
|
||||
done:
|
||||
@@ -1439,88 +1595,41 @@ static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_role *tgt,
|
||||
struct rtw89_mcc_role *src,
|
||||
bool ref_is_src)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u16 beacon_offset_us = ieee80211_tu_to_usec(config->beacon_offset);
|
||||
u32 bcn_intvl_src_us = ieee80211_tu_to_usec(src->beacon_interval);
|
||||
u32 cur_tbtt_ofst_src;
|
||||
u32 tsf_ofst_tgt;
|
||||
u32 remainder;
|
||||
u64 tbtt_tgt;
|
||||
u64 tsf_src;
|
||||
int ret;
|
||||
|
||||
ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src);
|
||||
if (ret) {
|
||||
rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
cur_tbtt_ofst_src = rtw89_mcc_get_tbtt_ofst(rtwdev, src, tsf_src);
|
||||
|
||||
if (ref_is_src)
|
||||
tbtt_tgt = tsf_src - cur_tbtt_ofst_src + beacon_offset_us;
|
||||
else
|
||||
tbtt_tgt = tsf_src - cur_tbtt_ofst_src +
|
||||
(bcn_intvl_src_us - beacon_offset_us);
|
||||
|
||||
div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder);
|
||||
tsf_ofst_tgt = bcn_intvl_src_us - remainder;
|
||||
|
||||
config->sync.macid_tgt = tgt->rtwvif_link->mac_id;
|
||||
config->sync.band_tgt = tgt->rtwvif_link->mac_idx;
|
||||
config->sync.port_tgt = tgt->rtwvif_link->port;
|
||||
config->sync.macid_src = src->rtwvif_link->mac_id;
|
||||
config->sync.band_src = src->rtwvif_link->mac_idx;
|
||||
config->sync.port_src = src->rtwvif_link->port;
|
||||
config->sync.offset = tsf_ofst_tgt / 1024;
|
||||
config->sync.enable = true;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC sync tbtt: tgt %d, src %d, offset %d\n",
|
||||
config->sync.macid_tgt, config->sync.macid_src,
|
||||
config->sync.offset);
|
||||
|
||||
rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link,
|
||||
config->sync.offset);
|
||||
}
|
||||
|
||||
static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
|
||||
u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
|
||||
struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link;
|
||||
s32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
|
||||
u64 tsf, start_tsf;
|
||||
u32 cur_tbtt_ofst;
|
||||
u64 min_time;
|
||||
u64 tsf_aux;
|
||||
int ret;
|
||||
|
||||
ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
|
||||
if (ret) {
|
||||
rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
|
||||
if (rtw89_concurrent_via_mrc(rtwdev))
|
||||
ret = __mrc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
|
||||
else
|
||||
ret = __mcc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
min_time = tsf;
|
||||
if (ref->is_go)
|
||||
if (ref->is_go || aux->is_go)
|
||||
min_time += ieee80211_tu_to_usec(RTW89_MCC_SHORT_TRIGGER_TIME);
|
||||
else
|
||||
min_time += ieee80211_tu_to_usec(RTW89_MCC_LONG_TRIGGER_TIME);
|
||||
|
||||
cur_tbtt_ofst = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf);
|
||||
start_tsf = tsf - cur_tbtt_ofst + bcn_intvl_ref_us - tob_ref_us;
|
||||
while (start_tsf < min_time)
|
||||
start_tsf += bcn_intvl_ref_us;
|
||||
if (start_tsf < min_time)
|
||||
start_tsf += roundup_u64(min_time - start_tsf, bcn_intvl_ref_us);
|
||||
|
||||
config->start_tsf = start_tsf;
|
||||
config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1537,13 +1646,11 @@ static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
|
||||
|
||||
switch (mcc->mode) {
|
||||
case RTW89_MCC_MODE_GO_STA:
|
||||
config->beacon_offset = RTW89_MCC_DFLT_BCN_OFST_TIME;
|
||||
config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
|
||||
if (ref->is_go) {
|
||||
rtw89_mcc_sync_tbtt(rtwdev, ref, aux, false);
|
||||
config->mcc_interval = ref->beacon_interval;
|
||||
rtw89_mcc_set_duration_go_sta(rtwdev, ref, aux);
|
||||
} else {
|
||||
rtw89_mcc_sync_tbtt(rtwdev, aux, ref, true);
|
||||
config->mcc_interval = aux->beacon_interval;
|
||||
rtw89_mcc_set_duration_go_sta(rtwdev, aux, ref);
|
||||
}
|
||||
@@ -1573,10 +1680,8 @@ static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
|
||||
|
||||
static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
|
||||
{
|
||||
const struct rtw89_mcc_courtesy_cfg *crtz = role->crtz;
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_pattern *pattern = &config->pattern;
|
||||
struct rtw89_mcc_courtesy *courtesy = &pattern->courtesy;
|
||||
struct rtw89_mcc_policy *policy = &role->policy;
|
||||
struct rtw89_fw_mcc_add_req req = {};
|
||||
const struct rtw89_chan *chan;
|
||||
@@ -1599,9 +1704,9 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro
|
||||
req.duration = role->duration;
|
||||
req.btc_in_2g = false;
|
||||
|
||||
if (courtesy->enable && courtesy->macid_src == req.macid) {
|
||||
req.courtesy_target = courtesy->macid_tgt;
|
||||
req.courtesy_num = courtesy->slot_num;
|
||||
if (crtz) {
|
||||
req.courtesy_target = crtz->macid_tgt;
|
||||
req.courtesy_num = crtz->slot_num;
|
||||
req.courtesy_en = true;
|
||||
}
|
||||
|
||||
@@ -1781,26 +1886,23 @@ static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_pattern *pattern = &config->pattern;
|
||||
struct rtw89_mcc_courtesy *courtesy = &pattern->courtesy;
|
||||
struct rtw89_fw_mrc_add_slot_arg *slot_arg_src;
|
||||
u8 slot_idx_tgt;
|
||||
|
||||
if (!courtesy->enable)
|
||||
return;
|
||||
|
||||
if (courtesy->macid_src == ref->rtwvif_link->mac_id) {
|
||||
if (ref->crtz) {
|
||||
slot_arg_src = &arg->slots[ref->slot_idx];
|
||||
slot_idx_tgt = aux->slot_idx;
|
||||
} else {
|
||||
slot_arg_src = &arg->slots[aux->slot_idx];
|
||||
slot_idx_tgt = ref->slot_idx;
|
||||
|
||||
slot_arg_src->courtesy_target = aux->slot_idx;
|
||||
slot_arg_src->courtesy_period = ref->crtz->slot_num;
|
||||
slot_arg_src->courtesy_en = true;
|
||||
}
|
||||
|
||||
slot_arg_src->courtesy_target = slot_idx_tgt;
|
||||
slot_arg_src->courtesy_period = courtesy->slot_num;
|
||||
slot_arg_src->courtesy_en = true;
|
||||
if (aux->crtz) {
|
||||
slot_arg_src = &arg->slots[aux->slot_idx];
|
||||
|
||||
slot_arg_src->courtesy_target = ref->slot_idx;
|
||||
slot_arg_src->courtesy_period = aux->crtz->slot_num;
|
||||
slot_arg_src->courtesy_en = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int __mrc_fw_start(struct rtw89_dev *rtwdev, bool replace)
|
||||
@@ -2000,30 +2102,24 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable)
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_role *aux = &mcc->role_aux;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_pattern *pattern = &config->pattern;
|
||||
struct rtw89_mcc_sync *sync = &config->sync;
|
||||
struct ieee80211_p2p_noa_desc noa_desc = {};
|
||||
u64 start_time = config->start_tsf;
|
||||
u32 interval = config->mcc_interval;
|
||||
struct rtw89_vif_link *rtwvif_go;
|
||||
u64 start_time;
|
||||
u32 duration;
|
||||
|
||||
if (mcc->mode != RTW89_MCC_MODE_GO_STA)
|
||||
return;
|
||||
|
||||
if (ref->is_go) {
|
||||
start_time = config->start_tsf;
|
||||
rtwvif_go = ref->rtwvif_link;
|
||||
start_time += ieee80211_tu_to_usec(ref->duration);
|
||||
duration = config->mcc_interval - ref->duration;
|
||||
} else if (aux->is_go) {
|
||||
start_time = config->start_tsf_in_aux_domain;
|
||||
rtwvif_go = aux->rtwvif_link;
|
||||
start_time += ieee80211_tu_to_usec(pattern->tob_ref) +
|
||||
ieee80211_tu_to_usec(config->beacon_offset) +
|
||||
ieee80211_tu_to_usec(pattern->toa_aux);
|
||||
duration = config->mcc_interval - aux->duration;
|
||||
|
||||
/* convert time domain from sta(ref) to GO(aux) */
|
||||
start_time += ieee80211_tu_to_usec(sync->offset);
|
||||
} else {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
|
||||
"MCC find no GO: skip updating beacon NoA\n");
|
||||
@@ -2127,6 +2223,12 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
struct rtw89_mcc_stop_sel {
|
||||
struct {
|
||||
const struct rtw89_vif_link *target;
|
||||
} hint;
|
||||
|
||||
/* selection content */
|
||||
bool filled;
|
||||
u8 mac_id;
|
||||
u8 slot_idx;
|
||||
};
|
||||
@@ -2136,6 +2238,7 @@ static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel,
|
||||
{
|
||||
sel->mac_id = mcc_role->rtwvif_link->mac_id;
|
||||
sel->slot_idx = mcc_role->slot_idx;
|
||||
sel->filled = true;
|
||||
}
|
||||
|
||||
static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
|
||||
@@ -2145,23 +2248,41 @@ static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
|
||||
{
|
||||
struct rtw89_mcc_stop_sel *sel = data;
|
||||
|
||||
if (mcc_role->rtwvif_link == sel->hint.target) {
|
||||
rtw89_mcc_stop_sel_fill(sel, mcc_role);
|
||||
return 1; /* break iteration */
|
||||
}
|
||||
|
||||
if (sel->filled)
|
||||
return 0;
|
||||
|
||||
if (!mcc_role->rtwvif_link->chanctx_assigned)
|
||||
return 0;
|
||||
|
||||
rtw89_mcc_stop_sel_fill(sel, mcc_role);
|
||||
return 1; /* break iteration */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw89_mcc_stop(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_mcc_stop(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chanctx_pause_parm *pause)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_role *ref = &mcc->role_ref;
|
||||
struct rtw89_mcc_stop_sel sel;
|
||||
struct rtw89_mcc_stop_sel sel = {
|
||||
.hint.target = pause ? pause->trigger : NULL,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!pause) {
|
||||
wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->chanctx_work);
|
||||
bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
|
||||
}
|
||||
|
||||
/* by default, stop at ref */
|
||||
rtw89_mcc_stop_sel_fill(&sel, ref);
|
||||
rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel);
|
||||
if (!sel.filled)
|
||||
rtw89_mcc_stop_sel_fill(&sel, ref);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop at <macid %d>\n", sel.mac_id);
|
||||
|
||||
@@ -2193,6 +2314,7 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_config old_cfg = *config;
|
||||
bool courtesy_changed;
|
||||
bool sync_changed;
|
||||
int ret;
|
||||
|
||||
@@ -2205,8 +2327,15 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (memcmp(&old_cfg.pattern.courtesy, &config->pattern.courtesy,
|
||||
sizeof(old_cfg.pattern.courtesy)) == 0)
|
||||
courtesy_changed = false;
|
||||
else
|
||||
courtesy_changed = true;
|
||||
|
||||
if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT ||
|
||||
config->pattern.plan != RTW89_MCC_PLAN_NO_BT) {
|
||||
config->pattern.plan != RTW89_MCC_PLAN_NO_BT ||
|
||||
courtesy_changed) {
|
||||
if (rtw89_concurrent_via_mrc(rtwdev))
|
||||
ret = __mrc_fw_start(rtwdev, true);
|
||||
else
|
||||
@@ -2238,7 +2367,7 @@ static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
|
||||
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
|
||||
struct rtw89_mcc_config *config = &mcc->config;
|
||||
struct rtw89_mcc_pattern *pattern = &config->pattern;
|
||||
s16 tolerance;
|
||||
u16 tolerance;
|
||||
u16 bcn_ofst;
|
||||
u16 diff;
|
||||
|
||||
@@ -2246,18 +2375,25 @@ static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
|
||||
return;
|
||||
|
||||
bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev);
|
||||
if (bcn_ofst == config->beacon_offset)
|
||||
return;
|
||||
|
||||
if (bcn_ofst > config->beacon_offset) {
|
||||
diff = bcn_ofst - config->beacon_offset;
|
||||
if (pattern->tob_aux < 0)
|
||||
tolerance = -pattern->tob_aux;
|
||||
else
|
||||
else if (pattern->toa_aux > 0)
|
||||
tolerance = pattern->toa_aux;
|
||||
else
|
||||
return; /* no chance to improve */
|
||||
} else {
|
||||
diff = config->beacon_offset - bcn_ofst;
|
||||
if (pattern->toa_aux < 0)
|
||||
tolerance = -pattern->toa_aux;
|
||||
else
|
||||
else if (pattern->tob_aux > 0)
|
||||
tolerance = pattern->tob_aux;
|
||||
else
|
||||
return; /* no chance to improve */
|
||||
}
|
||||
|
||||
if (diff <= tolerance)
|
||||
@@ -2504,7 +2640,7 @@ void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_pause_reasons rsn)
|
||||
const struct rtw89_chanctx_pause_parm *pause_parm)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
enum rtw89_entity_mode mode;
|
||||
@@ -2514,12 +2650,12 @@ void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
|
||||
if (hal->entity_pause)
|
||||
return;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", rsn);
|
||||
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", pause_parm->rsn);
|
||||
|
||||
mode = rtw89_get_entity_mode(rtwdev);
|
||||
switch (mode) {
|
||||
case RTW89_ENTITY_MODE_MCC:
|
||||
rtw89_mcc_stop(rtwdev);
|
||||
rtw89_mcc_stop(rtwdev, pause_parm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2744,7 +2880,7 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
|
||||
cur = rtw89_get_entity_mode(rtwdev);
|
||||
switch (cur) {
|
||||
case RTW89_ENTITY_MODE_MCC:
|
||||
rtw89_mcc_stop(rtwdev);
|
||||
rtw89_mcc_stop(rtwdev, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
#define RTW89_MCC_DFLT_TX_NULL_EARLY 3
|
||||
#define RTW89_MCC_DFLT_COURTESY_SLOT 3
|
||||
|
||||
#define RTW89_MCC_REQ_COURTESY_TIME 5
|
||||
#define RTW89_MCC_REQ_COURTESY(pattern, role) \
|
||||
({ \
|
||||
const struct rtw89_mcc_pattern *p = pattern; \
|
||||
p->tob_ ## role <= RTW89_MCC_REQ_COURTESY_TIME || \
|
||||
p->toa_ ## role <= RTW89_MCC_REQ_COURTESY_TIME; \
|
||||
})
|
||||
|
||||
#define NUM_OF_RTW89_MCC_ROLES 2
|
||||
|
||||
enum rtw89_chanctx_pause_reasons {
|
||||
@@ -38,6 +46,11 @@ enum rtw89_chanctx_pause_reasons {
|
||||
RTW89_CHANCTX_PAUSE_REASON_ROC,
|
||||
};
|
||||
|
||||
struct rtw89_chanctx_pause_parm {
|
||||
const struct rtw89_vif_link *trigger;
|
||||
enum rtw89_chanctx_pause_reasons rsn;
|
||||
};
|
||||
|
||||
struct rtw89_chanctx_cb_parm {
|
||||
int (*cb)(struct rtw89_dev *rtwdev, void *data);
|
||||
void *data;
|
||||
@@ -95,7 +108,7 @@ void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_idx idx,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_idx idx,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
void rtw89_entity_init(struct rtw89_dev *rtwdev);
|
||||
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
|
||||
@@ -105,7 +118,7 @@ void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_changes change);
|
||||
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
|
||||
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_pause_reasons rsn);
|
||||
const struct rtw89_chanctx_pause_parm *parm);
|
||||
void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chanctx_cb_parm *cb_parm);
|
||||
|
||||
|
||||
@@ -203,6 +203,23 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const u8 rtw89_ext_capa_sta[] = {
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
|
||||
static const struct wiphy_iftype_ext_capab rtw89_iftypes_ext_capa[] = {
|
||||
{
|
||||
.iftype = NL80211_IFTYPE_STATION,
|
||||
.extended_capabilities = rtw89_ext_capa_sta,
|
||||
.extended_capabilities_mask = rtw89_ext_capa_sta,
|
||||
.extended_capabilities_len = sizeof(rtw89_ext_capa_sta),
|
||||
/* relevant only if EHT is supported */
|
||||
.eml_capabilities = 0,
|
||||
.mld_capa_and_ops = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#define RTW89_6GHZ_SPAN_HEAD 6145
|
||||
#define RTW89_6GHZ_SPAN_IDX(center_freq) \
|
||||
((((int)(center_freq) - RTW89_6GHZ_SPAN_HEAD) / 5) / 2)
|
||||
@@ -211,6 +228,8 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
|
||||
[RTW89_6GHZ_SPAN_IDX(center_freq)] = { \
|
||||
.sar_subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
|
||||
.sar_subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
|
||||
.acpi_sar_subband_low = RTW89_ACPI_SAR_6GHZ_ ## subband_l, \
|
||||
.acpi_sar_subband_high = RTW89_ACPI_SAR_6GHZ_ ## subband_h, \
|
||||
.ant_gain_subband_low = RTW89_ANT_GAIN_6GHZ_ ## subband_l, \
|
||||
.ant_gain_subband_high = RTW89_ANT_GAIN_6GHZ_ ## subband_h, \
|
||||
}
|
||||
@@ -639,9 +658,17 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
|
||||
static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_core_tx_request *tx_req)
|
||||
{
|
||||
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
|
||||
struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
|
||||
struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
|
||||
|
||||
if (desc_info->mlo && !desc_info->sw_mld) {
|
||||
if (rtwsta_link)
|
||||
return rtw89_sta_get_main_macid(rtwsta_link->rtwsta);
|
||||
else
|
||||
return rtw89_vif_get_main_macid(rtwvif_link->rtwvif);
|
||||
}
|
||||
|
||||
if (!rtwsta_link)
|
||||
return rtwvif_link->mac_id;
|
||||
|
||||
@@ -671,7 +698,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *skb = tx_req->skb;
|
||||
u8 qsel, ch_dma;
|
||||
|
||||
qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT;
|
||||
qsel = rtw89_core_get_qsel_mgmt(rtwdev, tx_req);
|
||||
ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel);
|
||||
|
||||
desc_info->qsel = qsel;
|
||||
@@ -1104,39 +1131,23 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel)
|
||||
static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct rtw89_sta_link *rtwsta_link,
|
||||
struct sk_buff *skb, int *qsel, bool sw_mld)
|
||||
{
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
|
||||
struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
|
||||
struct rtw89_core_tx_request tx_req = {0};
|
||||
struct rtw89_sta_link *rtwsta_link = NULL;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
|
||||
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
struct rtw89_core_tx_request tx_req = {};
|
||||
int ret;
|
||||
|
||||
/* By default, driver writes tx via the link on HW-0. And then,
|
||||
* according to links' status, HW can change tx to another link.
|
||||
*/
|
||||
|
||||
if (rtwsta) {
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
if (unlikely(!rtwsta_link)) {
|
||||
rtw89_err(rtwdev, "tx: find no sta link on HW-0\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
}
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "tx: find no vif link on HW-0\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
tx_req.skb = skb;
|
||||
tx_req.vif = vif;
|
||||
tx_req.sta = sta;
|
||||
tx_req.rtwvif_link = rtwvif_link;
|
||||
tx_req.rtwsta_link = rtwsta_link;
|
||||
tx_req.desc_info.sw_mld = sw_mld;
|
||||
|
||||
rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
|
||||
rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
|
||||
@@ -1155,6 +1166,33 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel)
|
||||
{
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
|
||||
struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
|
||||
struct rtw89_sta_link *rtwsta_link = NULL;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
|
||||
if (rtwsta) {
|
||||
rtwsta_link = rtw89_get_designated_link(rtwsta);
|
||||
if (unlikely(!rtwsta_link)) {
|
||||
rtw89_err(rtwdev, "tx: find no sta designated link\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
rtwvif_link = rtwsta_link->rtwvif_link;
|
||||
} else {
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "tx: find no vif designated link\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
}
|
||||
|
||||
return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, false);
|
||||
}
|
||||
|
||||
static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info)
|
||||
{
|
||||
u32 dword = FIELD_PREP(RTW89_TXWD_BODY0_WP_OFFSET, desc_info->wp_offset) |
|
||||
@@ -1382,7 +1420,9 @@ static __le32 rtw89_build_txwd_body2_v2(struct rtw89_tx_desc_info *desc_info)
|
||||
|
||||
static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info)
|
||||
{
|
||||
u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq);
|
||||
u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) |
|
||||
FIELD_PREP(BE_TXD_BODY3_MLO_FLAG, desc_info->mlo) |
|
||||
FIELD_PREP(BE_TXD_BODY3_IS_MLD_SW_EN, desc_info->sw_mld);
|
||||
|
||||
return cpu_to_le32(dword);
|
||||
}
|
||||
@@ -1635,10 +1675,7 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
|
||||
u8 evm_pos = 0;
|
||||
int i;
|
||||
|
||||
/* FIXME: For single link, taking link on HW-0 here is okay. But, when
|
||||
* enabling multiple active links, we should determine the right link.
|
||||
*/
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, phy_ppdu->phy_idx);
|
||||
if (unlikely(!rtwsta_link))
|
||||
return;
|
||||
|
||||
@@ -2058,10 +2095,21 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
|
||||
break;
|
||||
|
||||
if (aid == vif->cfg.aid) {
|
||||
enum nl80211_he_ru_alloc rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1);
|
||||
enum nl80211_he_ru_alloc rua;
|
||||
|
||||
rtwvif->stats.rx_tf_acc++;
|
||||
rtwdev->stats.rx_tf_acc++;
|
||||
|
||||
/* The following only required for HE trigger frame, but we
|
||||
* cannot use UL HE-SIG-A2 reserved subfield to identify it
|
||||
* since some 11ax APs will fill it with all 0s, which will
|
||||
* be misunderstood as EHT trigger frame.
|
||||
*/
|
||||
if (bss_conf->eht_support)
|
||||
break;
|
||||
|
||||
rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1);
|
||||
|
||||
if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ &&
|
||||
rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106)
|
||||
rtwvif_link->pwr_diff_en = true;
|
||||
@@ -2152,8 +2200,10 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
|
||||
struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat;
|
||||
struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
|
||||
struct sk_buff *skb = iter_data->skb;
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu;
|
||||
bool is_mld = ieee80211_vif_is_mld(vif);
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
const u8 *bssid = iter_data->bssid;
|
||||
@@ -2165,10 +2215,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/* FIXME: For single link, taking link on HW-0 here is okay. But, when
|
||||
* enabling multiple active links, we should determine the right link.
|
||||
*/
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, desc_info->bb_sel);
|
||||
if (unlikely(!rtwvif_link))
|
||||
goto out;
|
||||
|
||||
@@ -2184,6 +2231,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
|
||||
if (!ether_addr_equal(bss_conf->bssid, bssid))
|
||||
goto out;
|
||||
|
||||
if (is_mld) {
|
||||
rx_status->link_valid = true;
|
||||
rx_status->link_id = rtwvif_link->link_id;
|
||||
}
|
||||
|
||||
if (ieee80211_is_beacon(hdr->frame_control)) {
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) {
|
||||
@@ -2482,7 +2534,8 @@ static void rtw89_core_rx_process_ppdu_sts(struct rtw89_dev *rtwdev,
|
||||
.len = skb->len,
|
||||
.to_self = desc_info->addr1_match,
|
||||
.rate = desc_info->data_rate,
|
||||
.mac_id = desc_info->mac_id};
|
||||
.mac_id = desc_info->mac_id,
|
||||
.phy_idx = desc_info->bb_sel};
|
||||
int ret;
|
||||
|
||||
if (desc_info->mac_info_valid) {
|
||||
@@ -2593,6 +2646,7 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
|
||||
desc_info->shift = le32_get_bits(rxd_s->dword0, BE_RXD_SHIFT_MASK);
|
||||
desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, BE_RXD_LONG_RXD);
|
||||
desc_info->pkt_type = le32_get_bits(rxd_s->dword0, BE_RXD_RPKT_TYPE_MASK);
|
||||
desc_info->bb_sel = le32_get_bits(rxd_s->dword0, BE_RXD_BB_SEL);
|
||||
if (desc_info->pkt_type == RTW89_CORE_RX_TYPE_PPDU_STAT)
|
||||
desc_info->mac_info_valid = true;
|
||||
|
||||
@@ -2665,10 +2719,7 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta)
|
||||
struct rtw89_sta_link *rtwsta_link;
|
||||
u8 mac_id = iter_data->mac_id;
|
||||
|
||||
/* FIXME: For single link, taking link on HW-0 here is okay. But, when
|
||||
* enabling multiple active links, we should determine the right link.
|
||||
*/
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, desc_info->bb_sel);
|
||||
if (unlikely(!rtwsta_link))
|
||||
return;
|
||||
|
||||
@@ -3117,9 +3168,9 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev,
|
||||
if (!rtwsta)
|
||||
return false;
|
||||
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
rtwsta_link = rtw89_get_designated_link(rtwsta);
|
||||
if (unlikely(!rtwsta_link)) {
|
||||
rtw89_err(rtwdev, "agg wait: find no link on HW-0\n");
|
||||
rtw89_err(rtwdev, "agg wait: find no designated link\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3284,8 +3335,10 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
|
||||
{
|
||||
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_sta_link *rtwsta_link;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct rtw89_sta *rtwsta;
|
||||
struct sk_buff *skb;
|
||||
int ret, qsel;
|
||||
|
||||
@@ -3298,6 +3351,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rtwsta = sta_to_rtwsta(sta);
|
||||
|
||||
skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, qos);
|
||||
if (!skb) {
|
||||
@@ -3309,7 +3363,13 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
|
||||
if (ps)
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
|
||||
|
||||
ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
|
||||
rtwsta_link = rtwsta->links[rtwvif_link->link_id];
|
||||
if (unlikely(!rtwsta_link)) {
|
||||
ret = -ENOLINK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, &qsel, true);
|
||||
if (ret) {
|
||||
rtw89_warn(rtwdev, "nullfunc transmit failed: %d\n", ret);
|
||||
dev_kfree_skb_any(skb);
|
||||
@@ -3329,6 +3389,9 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
|
||||
void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
struct rtw89_chanctx_pause_parm pause_parm = {
|
||||
.rsn = RTW89_CHANCTX_PAUSE_REASON_ROC,
|
||||
};
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
struct rtw89_roc *roc = &rtwvif->roc;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
@@ -3342,14 +3405,16 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
rtw89_leave_lps(rtwdev);
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, RTW89_ROC_BY_LINK_INDEX);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "roc start: find no link on HW-%u\n",
|
||||
RTW89_ROC_BY_LINK_INDEX);
|
||||
rtw89_err(rtwdev, "roc start: find no designated link\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC);
|
||||
roc->link_id = rtwvif_link->link_id;
|
||||
|
||||
pause_parm.trigger = rtwvif_link;
|
||||
rtw89_chanctx_pause(rtwdev, &pause_parm);
|
||||
|
||||
ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true);
|
||||
if (ret)
|
||||
@@ -3369,7 +3434,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
}
|
||||
|
||||
cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT);
|
||||
rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan);
|
||||
rtw89_config_roc_chandef(rtwdev, rtwvif_link, &roc_chan);
|
||||
rtw89_set_channel(rtwdev);
|
||||
|
||||
reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
|
||||
@@ -3398,10 +3463,10 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
rtw89_leave_lps(rtwdev);
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, RTW89_ROC_BY_LINK_INDEX);
|
||||
rtwvif_link = rtwvif->links[roc->link_id];
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "roc end: find no link on HW-%u\n",
|
||||
RTW89_ROC_BY_LINK_INDEX);
|
||||
rtw89_err(rtwdev, "roc end: find no link (link id %u)\n",
|
||||
roc->link_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3409,7 +3474,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr);
|
||||
|
||||
roc->state = RTW89_ROC_IDLE;
|
||||
rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL);
|
||||
rtw89_config_roc_chandef(rtwdev, rtwvif_link, NULL);
|
||||
rtw89_chanctx_proceed(rtwdev, NULL);
|
||||
ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false);
|
||||
if (ret)
|
||||
@@ -3577,6 +3642,98 @@ void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev,
|
||||
ewma_tp_init(&stats->rx_ewma_tp);
|
||||
}
|
||||
|
||||
#define RTW89_MLSR_GOTO_2GHZ_THRESHOLD -53
|
||||
#define RTW89_MLSR_EXIT_2GHZ_THRESHOLD -38
|
||||
static void rtw89_core_mlsr_link_decision(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif)
|
||||
{
|
||||
unsigned int sel_link_id = IEEE80211_MLD_MAX_NUM_LINKS;
|
||||
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
const struct rtw89_chan *chan;
|
||||
unsigned long usable_links;
|
||||
unsigned int link_id;
|
||||
u8 decided_bands;
|
||||
u8 rssi;
|
||||
|
||||
rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi);
|
||||
if (unlikely(!rssi))
|
||||
return;
|
||||
|
||||
if (RTW89_RSSI_RAW_TO_DBM(rssi) >= RTW89_MLSR_EXIT_2GHZ_THRESHOLD)
|
||||
decided_bands = BIT(RTW89_BAND_5G) | BIT(RTW89_BAND_6G);
|
||||
else if (RTW89_RSSI_RAW_TO_DBM(rssi) <= RTW89_MLSR_GOTO_2GHZ_THRESHOLD)
|
||||
decided_bands = BIT(RTW89_BAND_2G);
|
||||
else
|
||||
return;
|
||||
|
||||
usable_links = ieee80211_vif_usable_links(vif);
|
||||
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link))
|
||||
goto select;
|
||||
|
||||
chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
|
||||
if (decided_bands & BIT(chan->band_type))
|
||||
return;
|
||||
|
||||
usable_links &= ~BIT(rtwvif_link->link_id);
|
||||
|
||||
select:
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct ieee80211_channel *channel;
|
||||
enum rtw89_band band;
|
||||
|
||||
link_conf = rcu_dereference(vif->link_conf[link_id]);
|
||||
if (unlikely(!link_conf))
|
||||
continue;
|
||||
|
||||
channel = link_conf->chanreq.oper.chan;
|
||||
if (unlikely(!channel))
|
||||
continue;
|
||||
|
||||
band = rtw89_nl80211_to_hw_band(channel->band);
|
||||
if (decided_bands & BIT(band)) {
|
||||
sel_link_id = link_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (sel_link_id == IEEE80211_MLD_MAX_NUM_LINKS)
|
||||
return;
|
||||
|
||||
rtw89_core_mlsr_switch(rtwdev, rtwvif, sel_link_id);
|
||||
}
|
||||
|
||||
static void rtw89_core_mlo_track(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
|
||||
if (hal->disabled_dm_bitmap & BIT(RTW89_DM_MLO))
|
||||
return;
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
|
||||
continue;
|
||||
|
||||
switch (rtwvif->mlo_mode) {
|
||||
case RTW89_MLO_MODE_MLSR:
|
||||
rtw89_core_mlsr_link_decision(rtwdev, rtwvif);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
|
||||
@@ -3615,9 +3772,10 @@ static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work)
|
||||
rtw89_phy_antdiv_track(rtwdev);
|
||||
rtw89_phy_ul_tb_ctrl_track(rtwdev);
|
||||
rtw89_phy_edcca_track(rtwdev);
|
||||
rtw89_tas_track(rtwdev);
|
||||
rtw89_sar_track(rtwdev);
|
||||
rtw89_chanctx_track(rtwdev);
|
||||
rtw89_core_rfkill_poll(rtwdev, false);
|
||||
rtw89_core_mlo_track(rtwdev);
|
||||
|
||||
if (rtwdev->lps_enabled && !rtwdev->btc.lps)
|
||||
rtw89_enter_lps_track(rtwdev);
|
||||
@@ -3846,6 +4004,9 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev,
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false);
|
||||
|
||||
if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
|
||||
rtw89_p2p_noa_once_deinit(rtwvif_link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4361,17 +4522,18 @@ static void rtw89_init_eht_cap(struct rtw89_dev *rtwdev,
|
||||
|
||||
#define RTW89_SBAND_IFTYPES_NR 2
|
||||
|
||||
static void rtw89_init_he_eht_cap(struct rtw89_dev *rtwdev,
|
||||
enum nl80211_band band,
|
||||
struct ieee80211_supported_band *sband)
|
||||
static int rtw89_init_he_eht_cap(struct rtw89_dev *rtwdev,
|
||||
enum nl80211_band band,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
struct ieee80211_sband_iftype_data *iftype_data;
|
||||
enum nl80211_iftype iftype;
|
||||
int idx = 0;
|
||||
|
||||
iftype_data = kcalloc(RTW89_SBAND_IFTYPES_NR, sizeof(*iftype_data), GFP_KERNEL);
|
||||
iftype_data = devm_kcalloc(rtwdev->dev, RTW89_SBAND_IFTYPES_NR,
|
||||
sizeof(*iftype_data), GFP_KERNEL);
|
||||
if (!iftype_data)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
|
||||
switch (iftype) {
|
||||
@@ -4396,77 +4558,75 @@ static void rtw89_init_he_eht_cap(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
_ieee80211_set_sband_iftype_data(sband, iftype_data, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ieee80211_supported_band *
|
||||
rtw89_core_sband_dup(struct rtw89_dev *rtwdev,
|
||||
const struct ieee80211_supported_band *sband)
|
||||
{
|
||||
struct ieee80211_supported_band *dup;
|
||||
|
||||
dup = devm_kmemdup(rtwdev->dev, sband, sizeof(*sband), GFP_KERNEL);
|
||||
if (!dup)
|
||||
return NULL;
|
||||
|
||||
dup->channels = devm_kmemdup(rtwdev->dev, sband->channels,
|
||||
sizeof(*sband->channels) * sband->n_channels,
|
||||
GFP_KERNEL);
|
||||
if (!dup->channels)
|
||||
return NULL;
|
||||
|
||||
dup->bitrates = devm_kmemdup(rtwdev->dev, sband->bitrates,
|
||||
sizeof(*sband->bitrates) * sband->n_bitrates,
|
||||
GFP_KERNEL);
|
||||
if (!dup->bitrates)
|
||||
return NULL;
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
struct ieee80211_supported_band *sband_2ghz = NULL, *sband_5ghz = NULL;
|
||||
struct ieee80211_supported_band *sband_6ghz = NULL;
|
||||
u32 size = sizeof(struct ieee80211_supported_band);
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 support_bands = rtwdev->chip->support_bands;
|
||||
int ret;
|
||||
|
||||
if (support_bands & BIT(NL80211_BAND_2GHZ)) {
|
||||
sband_2ghz = kmemdup(&rtw89_sband_2ghz, size, GFP_KERNEL);
|
||||
if (!sband_2ghz)
|
||||
goto err;
|
||||
rtw89_init_ht_cap(rtwdev, &sband_2ghz->ht_cap);
|
||||
rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_2GHZ, sband_2ghz);
|
||||
hw->wiphy->bands[NL80211_BAND_2GHZ] = sband_2ghz;
|
||||
sband = rtw89_core_sband_dup(rtwdev, &rtw89_sband_2ghz);
|
||||
if (!sband)
|
||||
return -ENOMEM;
|
||||
rtw89_init_ht_cap(rtwdev, &sband->ht_cap);
|
||||
ret = rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_2GHZ, sband);
|
||||
if (ret)
|
||||
return ret;
|
||||
hw->wiphy->bands[NL80211_BAND_2GHZ] = sband;
|
||||
}
|
||||
|
||||
if (support_bands & BIT(NL80211_BAND_5GHZ)) {
|
||||
sband_5ghz = kmemdup(&rtw89_sband_5ghz, size, GFP_KERNEL);
|
||||
if (!sband_5ghz)
|
||||
goto err;
|
||||
rtw89_init_ht_cap(rtwdev, &sband_5ghz->ht_cap);
|
||||
rtw89_init_vht_cap(rtwdev, &sband_5ghz->vht_cap);
|
||||
rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_5GHZ, sband_5ghz);
|
||||
hw->wiphy->bands[NL80211_BAND_5GHZ] = sband_5ghz;
|
||||
sband = rtw89_core_sband_dup(rtwdev, &rtw89_sband_5ghz);
|
||||
if (!sband)
|
||||
return -ENOMEM;
|
||||
rtw89_init_ht_cap(rtwdev, &sband->ht_cap);
|
||||
rtw89_init_vht_cap(rtwdev, &sband->vht_cap);
|
||||
ret = rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_5GHZ, sband);
|
||||
if (ret)
|
||||
return ret;
|
||||
hw->wiphy->bands[NL80211_BAND_5GHZ] = sband;
|
||||
}
|
||||
|
||||
if (support_bands & BIT(NL80211_BAND_6GHZ)) {
|
||||
sband_6ghz = kmemdup(&rtw89_sband_6ghz, size, GFP_KERNEL);
|
||||
if (!sband_6ghz)
|
||||
goto err;
|
||||
rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_6GHZ, sband_6ghz);
|
||||
hw->wiphy->bands[NL80211_BAND_6GHZ] = sband_6ghz;
|
||||
sband = rtw89_core_sband_dup(rtwdev, &rtw89_sband_6ghz);
|
||||
if (!sband)
|
||||
return -ENOMEM;
|
||||
ret = rtw89_init_he_eht_cap(rtwdev, NL80211_BAND_6GHZ, sband);
|
||||
if (ret)
|
||||
return ret;
|
||||
hw->wiphy->bands[NL80211_BAND_6GHZ] = sband;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL;
|
||||
hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
|
||||
hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL;
|
||||
if (sband_2ghz)
|
||||
kfree((__force void *)sband_2ghz->iftype_data);
|
||||
if (sband_5ghz)
|
||||
kfree((__force void *)sband_5ghz->iftype_data);
|
||||
if (sband_6ghz)
|
||||
kfree((__force void *)sband_6ghz->iftype_data);
|
||||
kfree(sband_2ghz);
|
||||
kfree(sband_5ghz);
|
||||
kfree(sband_6ghz);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
|
||||
if (hw->wiphy->bands[NL80211_BAND_2GHZ])
|
||||
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
|
||||
if (hw->wiphy->bands[NL80211_BAND_5GHZ])
|
||||
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
|
||||
if (hw->wiphy->bands[NL80211_BAND_6GHZ])
|
||||
kfree((__force void *)hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
|
||||
kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
|
||||
kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
|
||||
kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]);
|
||||
hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL;
|
||||
hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
|
||||
hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL;
|
||||
}
|
||||
|
||||
static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev)
|
||||
@@ -4774,6 +4934,7 @@ struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif,
|
||||
|
||||
set_bit(index, rtwvif->links_inst_map);
|
||||
rtwvif->links[link_id] = rtwvif_link;
|
||||
list_add_tail(&rtwvif_link->dlink_schd, &rtwvif->dlink_pool);
|
||||
return rtwvif_link;
|
||||
|
||||
err:
|
||||
@@ -4794,6 +4955,7 @@ void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id)
|
||||
index = rtw89_vif_link_inst_get_index(link);
|
||||
clear_bit(index, rtwvif->links_inst_map);
|
||||
*container = NULL;
|
||||
list_del(&link->dlink_schd);
|
||||
}
|
||||
|
||||
struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
|
||||
@@ -4824,6 +4986,7 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
|
||||
|
||||
set_bit(index, rtwsta->links_inst_map);
|
||||
rtwsta->links[link_id] = rtwsta_link;
|
||||
list_add_tail(&rtwsta_link->dlink_schd, &rtwsta->dlink_pool);
|
||||
return rtwsta_link;
|
||||
|
||||
err:
|
||||
@@ -4844,6 +5007,7 @@ void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id)
|
||||
index = rtw89_sta_link_inst_get_index(link);
|
||||
clear_bit(index, rtwsta->links_inst_map);
|
||||
*container = NULL;
|
||||
list_del(&link->dlink_schd);
|
||||
}
|
||||
|
||||
int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
@@ -4860,6 +5024,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
continue;
|
||||
INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]);
|
||||
}
|
||||
INIT_LIST_HEAD(&rtwdev->scan_info.chan_list);
|
||||
INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work);
|
||||
INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work);
|
||||
INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work);
|
||||
@@ -4880,6 +5045,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
rtwdev->total_sta_assoc = 0;
|
||||
|
||||
rtw89_init_wait(&rtwdev->mcc.wait);
|
||||
rtw89_init_wait(&rtwdev->mlo.wait);
|
||||
rtw89_init_wait(&rtwdev->mac.fw_ofld_wait);
|
||||
rtw89_init_wait(&rtwdev->wow.wait);
|
||||
rtw89_init_wait(&rtwdev->mac.ps_wait);
|
||||
@@ -4901,7 +5067,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
|
||||
rtwdev->dbcc_en = true;
|
||||
rtwdev->mac.qta_mode = RTW89_QTA_DBCC;
|
||||
rtwdev->mlo_dbcc_mode = MLO_2_PLUS_0_1RF;
|
||||
rtwdev->mlo_dbcc_mode = MLO_1_PLUS_1_1RF;
|
||||
}
|
||||
|
||||
rtwdev->bbs[RTW89_PHY_0].phy_idx = RTW89_PHY_0;
|
||||
@@ -4919,7 +5085,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
|
||||
rtw89_ser_init(rtwdev);
|
||||
rtw89_entity_init(rtwdev);
|
||||
rtw89_tas_init(rtwdev);
|
||||
rtw89_sar_init(rtwdev);
|
||||
rtw89_phy_ant_gain_init(rtwdev);
|
||||
|
||||
return 0;
|
||||
@@ -4945,9 +5111,6 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
|
||||
struct rtw89_bb_ctx *bb = rtw89_get_bb_ctx(rtwdev, rtwvif_link->phy_idx);
|
||||
|
||||
rtwdev->scanning = true;
|
||||
rtw89_leave_lps(rtwdev);
|
||||
if (hw_scan)
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
|
||||
ether_addr_copy(rtwvif_link->mac_addr, mac_addr);
|
||||
rtw89_btc_ntfy_scan_start(rtwdev, rtwvif_link->phy_idx, chan->band_type);
|
||||
@@ -5062,6 +5225,76 @@ static void rtw89_core_setup_rfe_parms(struct rtw89_dev *rtwdev)
|
||||
rtw89_load_txpwr_table(rtwdev, rtwdev->rfe_parms->byr_tbl);
|
||||
}
|
||||
|
||||
int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
|
||||
u16 usable_links = ieee80211_vif_usable_links(vif);
|
||||
u16 active_links = vif->active_links;
|
||||
struct rtw89_vif_link *target, *cur;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
if (unlikely(!ieee80211_vif_is_mld(vif)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (unlikely(!(usable_links & BIT(link_id)))) {
|
||||
rtw89_warn(rtwdev, "%s: link id %u is not usable\n", __func__,
|
||||
link_id);
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
if (active_links == BIT(link_id))
|
||||
return 0;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_STATE, "%s: switch to link id %u MLSR\n",
|
||||
__func__, link_id);
|
||||
|
||||
rtw89_leave_lps(rtwdev);
|
||||
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
flush_work(&rtwdev->txq_work);
|
||||
|
||||
cur = rtw89_get_designated_link(rtwvif);
|
||||
|
||||
ret = ieee80211_set_active_links(vif, active_links | BIT(link_id));
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "%s: failed to activate link id %u\n",
|
||||
__func__, link_id);
|
||||
goto wake_queue;
|
||||
}
|
||||
|
||||
target = rtwvif->links[link_id];
|
||||
if (unlikely(!target)) {
|
||||
rtw89_err(rtwdev, "%s: failed to confirm link id %u\n",
|
||||
__func__, link_id);
|
||||
|
||||
ieee80211_set_active_links(vif, active_links);
|
||||
ret = -EFAULT;
|
||||
goto wake_queue;
|
||||
}
|
||||
|
||||
if (likely(cur))
|
||||
rtw89_fw_h2c_mlo_link_cfg(rtwdev, cur, false);
|
||||
|
||||
rtw89_fw_h2c_mlo_link_cfg(rtwdev, target, true);
|
||||
|
||||
ret = ieee80211_set_active_links(vif, BIT(link_id));
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "%s: failed to inactivate links 0x%x\n",
|
||||
__func__, active_links);
|
||||
|
||||
rtw89_chip_rfk_channel(rtwdev, target);
|
||||
|
||||
rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR;
|
||||
|
||||
wake_queue:
|
||||
ieee80211_wake_queues(rtwdev->hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
@@ -5305,8 +5538,11 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
||||
if (chip->chip_gen == RTW89_CHIP_BE)
|
||||
hw->wiphy->flags |= WIPHY_FLAG_DISABLE_WEXT;
|
||||
|
||||
if (rtwdev->support_mlo)
|
||||
if (rtwdev->support_mlo) {
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
|
||||
hw->wiphy->iftype_ext_capab = rtw89_iftypes_ext_capa;
|
||||
hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(rtw89_iftypes_ext_capa);
|
||||
}
|
||||
|
||||
hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
|
||||
@@ -5337,7 +5573,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
||||
ret = rtw89_regd_setup(rtwdev);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "failed to set up regd\n");
|
||||
goto err_free_supported_band;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hw->wiphy->sar_capa = &rtw89_sar_capa;
|
||||
@@ -5345,7 +5581,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
||||
ret = ieee80211_register_hw(hw);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "failed to register hw\n");
|
||||
goto err_free_supported_band;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rtw89_regd_init_hint(rtwdev);
|
||||
@@ -5360,8 +5596,6 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
||||
|
||||
err_unregister_hw:
|
||||
ieee80211_unregister_hw(hw);
|
||||
err_free_supported_band:
|
||||
rtw89_core_clr_supported_band(rtwdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -5372,7 +5606,6 @@ static void rtw89_core_unregister_hw(struct rtw89_dev *rtwdev)
|
||||
|
||||
rtw89_rfkill_polling_deinit(rtwdev);
|
||||
ieee80211_unregister_hw(hw);
|
||||
rtw89_core_clr_supported_band(rtwdev);
|
||||
}
|
||||
|
||||
int rtw89_core_register(struct rtw89_dev *rtwdev)
|
||||
@@ -5440,13 +5673,13 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
||||
if (!hw)
|
||||
goto err;
|
||||
|
||||
/* TODO: When driver MLO arch. is done, determine whether to support MLO
|
||||
* according to the following conditions.
|
||||
* 1. run with chanctx_ops
|
||||
* 2. chip->support_link_num != 0
|
||||
* 3. FW feature supports AP_LINK_PS
|
||||
/* Currently, our AP_LINK_PS handling only works for non-MLD softap
|
||||
* or MLD-single-link softap. If RTW89_MLD_NON_STA_LINK_NUM enlarges,
|
||||
* please tweak entire AP_LINKS_PS handling before supporting MLO.
|
||||
*/
|
||||
support_mlo = false;
|
||||
support_mlo = !no_chanctx && chip->support_link_num &&
|
||||
RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &early_fw) &&
|
||||
RTW89_MLD_NON_STA_LINK_NUM == 1;
|
||||
|
||||
hw->wiphy->iface_combinations = rtw89_iface_combs;
|
||||
|
||||
|
||||
@@ -798,6 +798,7 @@ struct rtw89_rx_phy_ppdu {
|
||||
u8 rssi[RF_PATH_MAX];
|
||||
u8 mac_id;
|
||||
u8 chan_idx;
|
||||
u8 phy_idx;
|
||||
u8 ie;
|
||||
u16 rate;
|
||||
u8 rpl_avg;
|
||||
@@ -1174,6 +1175,7 @@ struct rtw89_tx_desc_info {
|
||||
bool ldpc;
|
||||
bool upd_wlan_hdr;
|
||||
bool mlo;
|
||||
bool sw_mld;
|
||||
};
|
||||
|
||||
struct rtw89_core_tx_request {
|
||||
@@ -3379,6 +3381,7 @@ struct rtw89_sec_cam_entry {
|
||||
|
||||
struct rtw89_sta_link {
|
||||
struct rtw89_sta *rtwsta;
|
||||
struct list_head dlink_schd;
|
||||
unsigned int link_id;
|
||||
|
||||
u8 mac_id;
|
||||
@@ -3445,14 +3448,13 @@ enum rtw89_roc_state {
|
||||
RTW89_ROC_MGMT,
|
||||
};
|
||||
|
||||
#define RTW89_ROC_BY_LINK_INDEX 0
|
||||
|
||||
struct rtw89_roc {
|
||||
struct ieee80211_channel chan;
|
||||
struct wiphy_delayed_work roc_work;
|
||||
enum ieee80211_roc_type type;
|
||||
enum rtw89_roc_state state;
|
||||
int duration;
|
||||
unsigned int link_id;
|
||||
};
|
||||
|
||||
#define RTW89_P2P_MAX_NOA_NUM 2
|
||||
@@ -3483,8 +3485,17 @@ struct rtw89_p2p_noa_setter {
|
||||
u8 noa_index;
|
||||
};
|
||||
|
||||
struct rtw89_ps_noa_once_handler {
|
||||
bool in_duration;
|
||||
u64 tsf_begin;
|
||||
u64 tsf_end;
|
||||
struct wiphy_delayed_work set_work;
|
||||
struct wiphy_delayed_work clr_work;
|
||||
};
|
||||
|
||||
struct rtw89_vif_link {
|
||||
struct rtw89_vif *rtwvif;
|
||||
struct list_head dlink_schd;
|
||||
unsigned int link_id;
|
||||
|
||||
bool chanctx_assigned; /* only valid when running with chanctx_ops */
|
||||
@@ -3507,6 +3518,7 @@ struct rtw89_vif_link {
|
||||
u8 hit_rule;
|
||||
u8 last_noa_nr;
|
||||
u64 sync_bcn_tsf;
|
||||
bool rand_tsf_done;
|
||||
bool trigger;
|
||||
bool lsig_txop;
|
||||
u8 tgt_ind;
|
||||
@@ -3527,6 +3539,7 @@ struct rtw89_vif_link {
|
||||
struct rtw89_phy_rate_pattern rate_pattern;
|
||||
struct list_head general_pkt_list;
|
||||
struct rtw89_p2p_noa_setter p2p_noa;
|
||||
struct rtw89_ps_noa_once_handler noa_once;
|
||||
};
|
||||
|
||||
enum rtw89_lv1_rcvy_step {
|
||||
@@ -3986,7 +3999,11 @@ struct rtw89_rfe_parms {
|
||||
struct rtw89_txpwr_rule_2ghz rule_2ghz;
|
||||
struct rtw89_txpwr_rule_5ghz rule_5ghz;
|
||||
struct rtw89_txpwr_rule_6ghz rule_6ghz;
|
||||
struct rtw89_txpwr_rule_2ghz rule_da_2ghz;
|
||||
struct rtw89_txpwr_rule_5ghz rule_da_5ghz;
|
||||
struct rtw89_txpwr_rule_6ghz rule_da_6ghz;
|
||||
struct rtw89_tx_shape tx_shape;
|
||||
bool has_da;
|
||||
};
|
||||
|
||||
struct rtw89_rfe_parms_conf {
|
||||
@@ -4081,9 +4098,15 @@ struct rtw89_rfe_data {
|
||||
struct rtw89_txpwr_lmt_2ghz_data lmt_2ghz;
|
||||
struct rtw89_txpwr_lmt_5ghz_data lmt_5ghz;
|
||||
struct rtw89_txpwr_lmt_6ghz_data lmt_6ghz;
|
||||
struct rtw89_txpwr_lmt_2ghz_data da_lmt_2ghz;
|
||||
struct rtw89_txpwr_lmt_5ghz_data da_lmt_5ghz;
|
||||
struct rtw89_txpwr_lmt_6ghz_data da_lmt_6ghz;
|
||||
struct rtw89_txpwr_lmt_ru_2ghz_data lmt_ru_2ghz;
|
||||
struct rtw89_txpwr_lmt_ru_5ghz_data lmt_ru_5ghz;
|
||||
struct rtw89_txpwr_lmt_ru_6ghz_data lmt_ru_6ghz;
|
||||
struct rtw89_txpwr_lmt_ru_2ghz_data da_lmt_ru_2ghz;
|
||||
struct rtw89_txpwr_lmt_ru_5ghz_data da_lmt_ru_5ghz;
|
||||
struct rtw89_txpwr_lmt_ru_6ghz_data da_lmt_ru_6ghz;
|
||||
struct rtw89_tx_shape_lmt_data tx_shape_lmt;
|
||||
struct rtw89_tx_shape_lmt_ru_data tx_shape_lmt_ru;
|
||||
struct rtw89_rfe_parms rfe_parms;
|
||||
@@ -4284,12 +4307,14 @@ struct rtw89_chip_info {
|
||||
bool support_rnr;
|
||||
bool support_ant_gain;
|
||||
bool support_tas;
|
||||
bool support_sar_by_ant;
|
||||
bool ul_tb_waveform_ctrl;
|
||||
bool ul_tb_pwr_diff;
|
||||
bool rx_freq_frome_ie;
|
||||
bool hw_sec_hdr;
|
||||
bool hw_mgmt_tx_encrypt;
|
||||
bool hw_tkip_crypto;
|
||||
bool hw_mlo_bmc_crypto;
|
||||
u8 rf_path_num;
|
||||
u8 tx_nss;
|
||||
u8 rx_nss;
|
||||
@@ -4494,6 +4519,7 @@ enum rtw89_fw_feature {
|
||||
RTW89_FW_FEATURE_LPS_CH_INFO,
|
||||
RTW89_FW_FEATURE_NO_PHYCAP_P1,
|
||||
RTW89_FW_FEATURE_NO_POWER_DIFFERENCE,
|
||||
RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1,
|
||||
};
|
||||
|
||||
struct rtw89_fw_suit {
|
||||
@@ -4606,6 +4632,7 @@ struct rtw89_cam_info {
|
||||
enum rtw89_sar_sources {
|
||||
RTW89_SAR_SOURCE_NONE,
|
||||
RTW89_SAR_SOURCE_COMMON,
|
||||
RTW89_SAR_SOURCE_ACPI,
|
||||
|
||||
RTW89_SAR_SOURCE_NR,
|
||||
};
|
||||
@@ -4630,8 +4657,62 @@ struct rtw89_sar_cfg_common {
|
||||
s32 cfg[RTW89_SAR_SUBBAND_NR];
|
||||
};
|
||||
|
||||
enum rtw89_acpi_sar_subband {
|
||||
RTW89_ACPI_SAR_2GHZ_SUBBAND,
|
||||
RTW89_ACPI_SAR_5GHZ_SUBBAND_1, /* U-NII-1 */
|
||||
RTW89_ACPI_SAR_5GHZ_SUBBAND_2, /* U-NII-2 */
|
||||
RTW89_ACPI_SAR_5GHZ_SUBBAND_2E, /* U-NII-2-Extended */
|
||||
RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4, /* U-NII-3 and U-NII-4 */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_6, /* U-NII-6 */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */
|
||||
RTW89_ACPI_SAR_6GHZ_SUBBAND_8, /* U-NII-8 */
|
||||
|
||||
NUM_OF_RTW89_ACPI_SAR_SUBBAND,
|
||||
RTW89_ACPI_SAR_SUBBAND_NR_LEGACY = RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4 + 1,
|
||||
RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ = RTW89_ACPI_SAR_6GHZ_SUBBAND_8 + 1,
|
||||
};
|
||||
|
||||
#define TXPWR_FACTOR_OF_RTW89_ACPI_SAR 3 /* unit: 0.125 dBm */
|
||||
#define MAX_VAL_OF_RTW89_ACPI_SAR S16_MAX
|
||||
#define MIN_VAL_OF_RTW89_ACPI_SAR S16_MIN
|
||||
#define MAX_NUM_OF_RTW89_ACPI_SAR_TBL 6
|
||||
#define NUM_OF_RTW89_ACPI_SAR_RF_PATH (RF_PATH_B + 1)
|
||||
|
||||
struct rtw89_sar_entry_from_acpi {
|
||||
s16 v[NUM_OF_RTW89_ACPI_SAR_SUBBAND][NUM_OF_RTW89_ACPI_SAR_RF_PATH];
|
||||
};
|
||||
|
||||
struct rtw89_sar_table_from_acpi {
|
||||
/* If this table is active, must fill all fields according to either
|
||||
* configuration in BIOS or some default values for SAR to work well.
|
||||
*/
|
||||
struct rtw89_sar_entry_from_acpi entries[RTW89_REGD_NUM];
|
||||
};
|
||||
|
||||
struct rtw89_sar_indicator_from_acpi {
|
||||
bool enable_sync;
|
||||
unsigned int fields;
|
||||
u8 (*rfpath_to_antidx)(enum rtw89_rf_path rfpath);
|
||||
|
||||
/* Select among @tables of container, rtw89_sar_cfg_acpi, by path.
|
||||
* Not design with pointers since addresses will be invalid after
|
||||
* sync content with local container instance.
|
||||
*/
|
||||
u8 tblsel[NUM_OF_RTW89_ACPI_SAR_RF_PATH];
|
||||
};
|
||||
|
||||
struct rtw89_sar_cfg_acpi {
|
||||
u8 downgrade_2tx;
|
||||
unsigned int valid_num;
|
||||
struct rtw89_sar_table_from_acpi tables[MAX_NUM_OF_RTW89_ACPI_SAR_TBL];
|
||||
struct rtw89_sar_indicator_from_acpi indicator;
|
||||
};
|
||||
|
||||
struct rtw89_sar_info {
|
||||
/* used to decide how to acces SAR cfg union */
|
||||
/* used to decide how to access SAR cfg union */
|
||||
enum rtw89_sar_sources src;
|
||||
|
||||
/* reserved for different knids of SAR cfg struct.
|
||||
@@ -4639,6 +4720,7 @@ struct rtw89_sar_info {
|
||||
*/
|
||||
union {
|
||||
struct rtw89_sar_cfg_common cfg_common;
|
||||
struct rtw89_sar_cfg_acpi cfg_acpi;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4674,11 +4756,14 @@ struct rtw89_ant_gain_info {
|
||||
struct rtw89_6ghz_span {
|
||||
enum rtw89_sar_subband sar_subband_low;
|
||||
enum rtw89_sar_subband sar_subband_high;
|
||||
enum rtw89_acpi_sar_subband acpi_sar_subband_low;
|
||||
enum rtw89_acpi_sar_subband acpi_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_ACPI_SAR_SPAN_VALID(span) ((span)->acpi_sar_subband_high)
|
||||
#define RTW89_ANT_GAIN_SPAN_VALID(span) ((span)->ant_gain_subband_high)
|
||||
|
||||
enum rtw89_tas_state {
|
||||
@@ -4692,6 +4777,7 @@ enum rtw89_tas_state {
|
||||
struct rtw89_tas_info {
|
||||
u16 tx_ratio_history[RTW89_TAS_TX_RATIO_WINDOW];
|
||||
u64 txpwr_history[RTW89_TAS_TXPWR_WINDOW];
|
||||
u8 enabled_countries;
|
||||
u8 txpwr_head_idx;
|
||||
u8 txpwr_tail_idx;
|
||||
u8 tx_ratio_idx;
|
||||
@@ -4765,6 +4851,7 @@ enum rtw89_dm_type {
|
||||
RTW89_DM_DYNAMIC_EDCCA,
|
||||
RTW89_DM_THERMAL_PROTECT,
|
||||
RTW89_DM_TAS,
|
||||
RTW89_DM_MLO,
|
||||
};
|
||||
|
||||
#define RTW89_THERMAL_PROT_LV_MAX 5
|
||||
@@ -4786,6 +4873,7 @@ struct rtw89_hal {
|
||||
bool no_mcs_12_13;
|
||||
|
||||
atomic_t roc_chanctx_idx;
|
||||
u8 roc_link_index;
|
||||
|
||||
DECLARE_BITMAP(changes, NUM_OF_RTW89_CHANCTX_CHANGES);
|
||||
DECLARE_BITMAP(entity_map, NUM_OF_RTW89_CHANCTX);
|
||||
@@ -5207,6 +5295,8 @@ struct rtw89_regulatory_info {
|
||||
const struct rtw89_regd *regd;
|
||||
enum rtw89_reg_6ghz_power reg_6ghz_power;
|
||||
struct rtw89_reg_6ghz_tpe reg_6ghz_tpe;
|
||||
bool txpwr_uk_follow_etsi;
|
||||
|
||||
DECLARE_BITMAP(block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
|
||||
DECLARE_BITMAP(block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
|
||||
DECLARE_BITMAP(block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
|
||||
@@ -5360,9 +5450,10 @@ struct rtw89_early_h2c {
|
||||
struct rtw89_hw_scan_info {
|
||||
struct rtw89_vif_link *scanning_vif;
|
||||
struct list_head pkt_list[NUM_NL80211_BANDS];
|
||||
struct list_head chan_list;
|
||||
struct rtw89_chan op_chan;
|
||||
bool connected;
|
||||
bool abort;
|
||||
u32 last_chan_idx;
|
||||
};
|
||||
|
||||
enum rtw89_phy_bb_gain_band {
|
||||
@@ -5574,6 +5665,8 @@ struct rtw89_mcc_role {
|
||||
struct rtw89_mcc_policy policy;
|
||||
struct rtw89_mcc_limit limit;
|
||||
|
||||
const struct rtw89_mcc_courtesy_cfg *crtz;
|
||||
|
||||
/* only valid when running with FW MRC mechanism */
|
||||
u8 slot_idx;
|
||||
|
||||
@@ -5591,13 +5684,16 @@ struct rtw89_mcc_bt_role {
|
||||
u16 duration; /* TU */
|
||||
};
|
||||
|
||||
struct rtw89_mcc_courtesy {
|
||||
bool enable;
|
||||
struct rtw89_mcc_courtesy_cfg {
|
||||
u8 slot_num;
|
||||
u8 macid_src;
|
||||
u8 macid_tgt;
|
||||
};
|
||||
|
||||
struct rtw89_mcc_courtesy {
|
||||
struct rtw89_mcc_courtesy_cfg ref;
|
||||
struct rtw89_mcc_courtesy_cfg aux;
|
||||
};
|
||||
|
||||
enum rtw89_mcc_plan {
|
||||
RTW89_MCC_PLAN_TAIL_BT,
|
||||
RTW89_MCC_PLAN_MID_BT,
|
||||
@@ -5631,6 +5727,7 @@ struct rtw89_mcc_config {
|
||||
struct rtw89_mcc_pattern pattern;
|
||||
struct rtw89_mcc_sync sync;
|
||||
u64 start_tsf;
|
||||
u64 start_tsf_in_aux_domain;
|
||||
u16 mcc_interval; /* TU */
|
||||
u16 beacon_offset; /* TU */
|
||||
};
|
||||
@@ -5651,6 +5748,16 @@ struct rtw89_mcc_info {
|
||||
struct rtw89_mcc_config config;
|
||||
};
|
||||
|
||||
enum rtw89_mlo_mode {
|
||||
RTW89_MLO_MODE_MLSR = 0,
|
||||
|
||||
NUM_OF_RTW89_MLO_MODE,
|
||||
};
|
||||
|
||||
struct rtw89_mlo_info {
|
||||
struct rtw89_wait_info wait;
|
||||
};
|
||||
|
||||
struct rtw89_dev {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@@ -5666,6 +5773,7 @@ struct rtw89_dev {
|
||||
const struct rtw89_rfe_parms *rfe_parms;
|
||||
struct rtw89_hal hal;
|
||||
struct rtw89_mcc_info mcc;
|
||||
struct rtw89_mlo_info mlo;
|
||||
struct rtw89_mac_info mac;
|
||||
struct rtw89_fw_info fw;
|
||||
struct rtw89_hci_info hci;
|
||||
@@ -5802,6 +5910,9 @@ struct rtw89_vif {
|
||||
struct rtw89_roc roc;
|
||||
bool offchan;
|
||||
|
||||
enum rtw89_mlo_mode mlo_mode;
|
||||
|
||||
struct list_head dlink_pool;
|
||||
u8 links_inst_valid_num;
|
||||
DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
|
||||
struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
@@ -5841,6 +5952,7 @@ struct rtw89_sta {
|
||||
|
||||
DECLARE_BITMAP(pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
|
||||
|
||||
struct list_head dlink_pool;
|
||||
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];
|
||||
@@ -5936,6 +6048,12 @@ rtw89_assoc_link_rcu_dereference(struct rtw89_dev *rtwdev, u8 macid)
|
||||
return rcu_dereference(rtwdev->assoc_link_on_macid[macid]);
|
||||
}
|
||||
|
||||
#define rtw89_get_designated_link(links_holder) \
|
||||
({ \
|
||||
typeof(links_holder) p = links_holder; \
|
||||
list_first_entry_or_null(&p->dlink_pool, typeof(*p->links_inst), dlink_schd); \
|
||||
})
|
||||
|
||||
static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_core_tx_request *tx_req)
|
||||
{
|
||||
@@ -6825,9 +6943,14 @@ static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev,
|
||||
|
||||
static inline u8 rtw89_regd_get(struct rtw89_dev *rtwdev, u8 band)
|
||||
{
|
||||
const struct rtw89_regd *regd = rtwdev->regulatory.regd;
|
||||
const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
const struct rtw89_regd *regd = regulatory->regd;
|
||||
u8 txpwr_regd = regd->txpwr_regd[band];
|
||||
|
||||
return regd->txpwr_regd[band];
|
||||
if (regulatory->txpwr_uk_follow_etsi && txpwr_regd == RTW89_UK)
|
||||
return RTW89_ETSI;
|
||||
|
||||
return txpwr_regd;
|
||||
}
|
||||
|
||||
static inline void rtw89_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en,
|
||||
@@ -7185,6 +7308,7 @@ void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
|
||||
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
|
||||
int rtw89_regd_setup(struct rtw89_dev *rtwdev);
|
||||
int rtw89_regd_init_hint(struct rtw89_dev *rtwdev);
|
||||
const char *rtw89_regd_get_string(enum rtw89_regulation_type regd);
|
||||
void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_traffic_stats *stats);
|
||||
int rtw89_wait_for_cond(struct rtw89_wait_info *wait, unsigned int cond);
|
||||
@@ -7206,5 +7330,7 @@ void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct ieee80211_bss_conf *bss_conf);
|
||||
void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event);
|
||||
int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
unsigned int link_id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -85,6 +85,7 @@ struct rtw89_debugfs {
|
||||
struct rtw89_debugfs_priv phy_info;
|
||||
struct rtw89_debugfs_priv stations;
|
||||
struct rtw89_debugfs_priv disable_dm;
|
||||
struct rtw89_debugfs_priv mlo_mode;
|
||||
};
|
||||
|
||||
struct rtw89_debugfs_iter_data {
|
||||
@@ -854,45 +855,21 @@ static ssize_t __print_txpwr_map(struct rtw89_dev *rtwdev, char *buf, size_t buf
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
#define case_REGD(_regd) \
|
||||
case RTW89_ ## _regd: \
|
||||
p += scnprintf(p, end - p, #_regd "\n"); \
|
||||
break
|
||||
|
||||
static int __print_regd(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
const struct rtw89_chan *chan)
|
||||
{
|
||||
const struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
u8 band = chan->band_type;
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
|
||||
switch (regd) {
|
||||
default:
|
||||
p += scnprintf(p, end - p, "UNKNOWN: %d\n", regd);
|
||||
break;
|
||||
case_REGD(WW);
|
||||
case_REGD(ETSI);
|
||||
case_REGD(FCC);
|
||||
case_REGD(MKK);
|
||||
case_REGD(NA);
|
||||
case_REGD(IC);
|
||||
case_REGD(KCC);
|
||||
case_REGD(NCC);
|
||||
case_REGD(CHILE);
|
||||
case_REGD(ACMA);
|
||||
case_REGD(MEXICO);
|
||||
case_REGD(UKRAINE);
|
||||
case_REGD(CN);
|
||||
case_REGD(QATAR);
|
||||
case_REGD(UK);
|
||||
case_REGD(THAILAND);
|
||||
}
|
||||
p += scnprintf(p, end - p, "%s\n", rtw89_regd_get_string(regd));
|
||||
p += scnprintf(p, end - p, "\t(txpwr UK follow ETSI: %s)\n",
|
||||
str_yes_no(regulatory->txpwr_uk_follow_etsi));
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
#undef case_REGD
|
||||
|
||||
struct dbgfs_txpwr_table {
|
||||
const struct txpwr_map *byr;
|
||||
const struct txpwr_map *lmt;
|
||||
@@ -949,6 +926,7 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
|
||||
char *buf, size_t bufsz)
|
||||
{
|
||||
enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
|
||||
struct rtw89_sar_parm sar_parm = {};
|
||||
const struct dbgfs_txpwr_table *tbl;
|
||||
const struct rtw89_chan *chan;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
@@ -958,11 +936,12 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
|
||||
|
||||
rtw89_leave_ps_mode(rtwdev);
|
||||
chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
|
||||
sar_parm.center_freq = chan->freq;
|
||||
|
||||
p += rtw89_debug_priv_txpwr_table_get_regd(rtwdev, p, end - p, chan);
|
||||
|
||||
p += scnprintf(p, end - p, "[SAR]\n");
|
||||
p += rtw89_print_sar(rtwdev, p, end - p, chan->freq);
|
||||
p += rtw89_print_sar(rtwdev, p, end - p, &sar_parm);
|
||||
|
||||
p += scnprintf(p, end - p, "[TAS]\n");
|
||||
p += rtw89_print_tas(rtwdev, p, end - p);
|
||||
@@ -3993,14 +3972,16 @@ static int rtw89_dump_pkt_offload(char *buf, size_t bufsz, struct list_head *pkt
|
||||
|
||||
static int rtw89_vif_link_ids_get(struct rtw89_dev *rtwdev,
|
||||
char *buf, size_t bufsz, u8 *mac,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
bool designated)
|
||||
{
|
||||
struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
|
||||
p += scnprintf(p, end - p, " [%u] %pM\n", rtwvif_link->mac_id,
|
||||
rtwvif_link->mac_addr);
|
||||
p += scnprintf(p, end - p, "\tlink_id=%u\n", rtwvif_link->link_id);
|
||||
p += scnprintf(p, end - p, "\tlink_id=%u%s\n", rtwvif_link->link_id,
|
||||
designated ? " (*)" : "");
|
||||
p += scnprintf(p, end - p, "\tbssid_cam_idx=%u\n",
|
||||
bssid_cam->bssid_cam_idx);
|
||||
p += rtw89_dump_addr_cam(rtwdev, p, end - p, &rtwvif_link->addr_cam);
|
||||
@@ -4017,15 +3998,19 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
(struct rtw89_debugfs_iter_data *)data;
|
||||
struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
|
||||
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
|
||||
struct rtw89_vif_link *designated_link;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
size_t bufsz = iter_data->bufsz;
|
||||
char *buf = iter_data->buf;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
unsigned int link_id;
|
||||
|
||||
designated_link = rtw89_get_designated_link(rtwvif);
|
||||
|
||||
p += scnprintf(p, end - p, "VIF %pM\n", rtwvif->mac_addr);
|
||||
rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
|
||||
p += rtw89_vif_link_ids_get(rtwdev, p, end - p, mac, rtwvif_link);
|
||||
p += rtw89_vif_link_ids_get(rtwdev, p, end - p, mac, rtwvif_link,
|
||||
rtwvif_link == designated_link);
|
||||
|
||||
rtw89_debugfs_iter_data_next(iter_data, p, end - p, p - buf);
|
||||
}
|
||||
@@ -4055,7 +4040,8 @@ static int rtw89_dump_ba_cam(struct rtw89_dev *rtwdev,
|
||||
|
||||
static int rtw89_sta_link_ids_get(struct rtw89_dev *rtwdev,
|
||||
char *buf, size_t bufsz,
|
||||
struct rtw89_sta_link *rtwsta_link)
|
||||
struct rtw89_sta_link *rtwsta_link,
|
||||
bool designated)
|
||||
{
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
@@ -4069,7 +4055,8 @@ static int rtw89_sta_link_ids_get(struct rtw89_dev *rtwdev,
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
p += scnprintf(p, end - p, "\tlink_id=%u\n", rtwsta_link->link_id);
|
||||
p += scnprintf(p, end - p, "\tlink_id=%u%s\n", rtwsta_link->link_id,
|
||||
designated ? " (*)" : "");
|
||||
p += rtw89_dump_addr_cam(rtwdev, p, end - p, &rtwsta_link->addr_cam);
|
||||
p += rtw89_dump_ba_cam(rtwdev, p, end - p, rtwsta_link);
|
||||
|
||||
@@ -4082,16 +4069,20 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
|
||||
(struct rtw89_debugfs_iter_data *)data;
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
|
||||
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
|
||||
struct rtw89_sta_link *designated_link;
|
||||
struct rtw89_sta_link *rtwsta_link;
|
||||
size_t bufsz = iter_data->bufsz;
|
||||
char *buf = iter_data->buf;
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
unsigned int link_id;
|
||||
|
||||
designated_link = rtw89_get_designated_link(rtwsta);
|
||||
|
||||
p += scnprintf(p, end - p, "STA %pM %s\n", sta->addr,
|
||||
sta->tdls ? "(TDLS)" : "");
|
||||
rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
|
||||
p += rtw89_sta_link_ids_get(rtwdev, p, end - p, rtwsta_link);
|
||||
p += rtw89_sta_link_ids_get(rtwdev, p, end - p, rtwsta_link,
|
||||
rtwsta_link == designated_link);
|
||||
|
||||
rtw89_debugfs_iter_data_next(iter_data, p, end - p, p - buf);
|
||||
}
|
||||
@@ -4146,6 +4137,35 @@ static ssize_t rtw89_debug_priv_stations_get(struct rtw89_dev *rtwdev,
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
static void rtw89_debug_disable_dm_cfg_bmap(struct rtw89_dev *rtwdev, u32 new)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
u32 old = hal->disabled_dm_bitmap;
|
||||
|
||||
if (new == old)
|
||||
return;
|
||||
|
||||
hal->disabled_dm_bitmap = new;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_STATE, "Disable DM: 0x%x -> 0x%x\n", old, new);
|
||||
}
|
||||
|
||||
static void rtw89_debug_disable_dm_set_flag(struct rtw89_dev *rtwdev, u8 flag)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
u32 cur = hal->disabled_dm_bitmap;
|
||||
|
||||
rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur | BIT(flag));
|
||||
}
|
||||
|
||||
static void rtw89_debug_disable_dm_clr_flag(struct rtw89_dev *rtwdev, u8 flag)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
u32 cur = hal->disabled_dm_bitmap;
|
||||
|
||||
rtw89_debug_disable_dm_cfg_bmap(rtwdev, cur & ~BIT(flag));
|
||||
}
|
||||
|
||||
#define DM_INFO(type) {RTW89_DM_ ## type, #type}
|
||||
|
||||
static const struct rtw89_disabled_dm_info {
|
||||
@@ -4155,6 +4175,7 @@ static const struct rtw89_disabled_dm_info {
|
||||
DM_INFO(DYNAMIC_EDCCA),
|
||||
DM_INFO(THERMAL_PROTECT),
|
||||
DM_INFO(TAS),
|
||||
DM_INFO(MLO),
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
@@ -4188,7 +4209,6 @@ rtw89_debug_priv_disable_dm_set(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_debugfs_priv *debugfs_priv,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
u32 conf;
|
||||
int ret;
|
||||
|
||||
@@ -4196,7 +4216,83 @@ rtw89_debug_priv_disable_dm_set(struct rtw89_dev *rtwdev,
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
hal->disabled_dm_bitmap = conf;
|
||||
rtw89_debug_disable_dm_cfg_bmap(rtwdev, conf);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void rtw89_debug_mlo_mode_set_mlsr(struct rtw89_dev *rtwdev,
|
||||
unsigned int link_id)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
continue;
|
||||
|
||||
rtw89_core_mlsr_switch(rtwdev, rtwvif, link_id);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
rtw89_debug_priv_mlo_mode_get(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_debugfs_priv *debugfs_priv,
|
||||
char *buf, size_t bufsz)
|
||||
{
|
||||
bool mlo_dm_dis = rtwdev->hal.disabled_dm_bitmap & BIT(RTW89_DM_MLO);
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
int count = 0;
|
||||
|
||||
p += scnprintf(p, end - p, "MLD(s) status: (MLO DM: %s)\n",
|
||||
str_disable_enable(mlo_dm_dis));
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
continue;
|
||||
|
||||
p += scnprintf(p, end - p,
|
||||
"\t#%u: MLO mode %x, valid 0x%x, active 0x%x\n",
|
||||
count++, rtwvif->mlo_mode, vif->valid_links,
|
||||
vif->active_links);
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
p += scnprintf(p, end - p, "\t(None)\n");
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_debugfs_priv *debugfs_priv,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u8 num, mlo_mode;
|
||||
u32 argv;
|
||||
|
||||
num = sscanf(buf, "%hhx %u", &mlo_mode, &argv);
|
||||
if (num != 2)
|
||||
return -EINVAL;
|
||||
|
||||
rtw89_debug_disable_dm_set_flag(rtwdev, RTW89_DM_MLO);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_STATE, "Set MLO mode to %x\n", mlo_mode);
|
||||
|
||||
switch (mlo_mode) {
|
||||
case RTW89_MLO_MODE_MLSR:
|
||||
rtw89_debug_mlo_mode_set_mlsr(rtwdev, argv);
|
||||
break;
|
||||
default:
|
||||
rtw89_debug(rtwdev, RTW89_DBG_STATE, "Unsupported MLO mode\n");
|
||||
rtw89_debug_disable_dm_clr_flag(rtwdev, RTW89_DM_MLO);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -4257,7 +4353,8 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = {
|
||||
.fw_log_manual = rtw89_debug_priv_set(fw_log_manual, WLOCK),
|
||||
.phy_info = rtw89_debug_priv_get(phy_info),
|
||||
.stations = rtw89_debug_priv_get(stations, RLOCK),
|
||||
.disable_dm = rtw89_debug_priv_set_and_get(disable_dm),
|
||||
.disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK),
|
||||
.mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK),
|
||||
};
|
||||
|
||||
#define rtw89_debugfs_add(name, mode, fopname, parent) \
|
||||
@@ -4302,6 +4399,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top
|
||||
rtw89_debugfs_add_r(phy_info);
|
||||
rtw89_debugfs_add_r(stations);
|
||||
rtw89_debugfs_add_rw(disable_dm);
|
||||
rtw89_debugfs_add_rw(mlo_mode);
|
||||
}
|
||||
|
||||
void rtw89_debugfs_init(struct rtw89_dev *rtwdev)
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "util.h"
|
||||
#include "wow.h"
|
||||
|
||||
static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev);
|
||||
|
||||
struct rtw89_eapol_2_of_2 {
|
||||
u8 gtkbody[14];
|
||||
u8 key_des_ver;
|
||||
@@ -554,7 +556,7 @@ const struct rtw89_mfw_hdr *rtw89_mfw_get_hdr_ptr(struct rtw89_dev *rtwdev,
|
||||
if (sizeof(*mfw_hdr) > firmware->size)
|
||||
return NULL;
|
||||
|
||||
mfw_hdr = (const struct rtw89_mfw_hdr *)firmware->data;
|
||||
mfw_hdr = (const struct rtw89_mfw_hdr *)&firmware->data[0];
|
||||
|
||||
if (mfw_hdr->sig != RTW89_MFW_SIG)
|
||||
return NULL;
|
||||
@@ -850,6 +852,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
|
||||
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1),
|
||||
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1),
|
||||
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE),
|
||||
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 71, 0, BEACON_LOSS_COUNT_V1),
|
||||
};
|
||||
|
||||
static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
|
||||
@@ -1018,7 +1021,7 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]);
|
||||
regs = kcalloc(n_regs, sizeof(tbl->regs[0]), GFP_KERNEL);
|
||||
regs = kcalloc(n_regs, sizeof(*regs), GFP_KERNEL);
|
||||
if (!regs)
|
||||
goto out;
|
||||
|
||||
@@ -1298,6 +1301,18 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, lmt_6ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_2GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_2ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_5GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_5ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_6GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_6ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, lmt_ru_2ghz.conf) }, NULL,
|
||||
@@ -1310,6 +1325,18 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, lmt_ru_6ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_2GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_2ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_5ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_6ghz.conf) }, NULL,
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT] = {
|
||||
rtw89_fw_recognize_txpwr_from_elm,
|
||||
{ .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt.conf) }, NULL,
|
||||
@@ -2483,7 +2510,7 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
|
||||
if (enable)
|
||||
comp = BIT(RTW89_FW_LOG_COMP_INIT) | BIT(RTW89_FW_LOG_COMP_TASK) |
|
||||
BIT(RTW89_FW_LOG_COMP_PS) | BIT(RTW89_FW_LOG_COMP_ERROR) |
|
||||
BIT(RTW89_FW_LOG_COMP_SCAN);
|
||||
BIT(RTW89_FW_LOG_COMP_MLO) | BIT(RTW89_FW_LOG_COMP_SCAN);
|
||||
|
||||
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LOG_CFG_LEN);
|
||||
if (!skb) {
|
||||
@@ -3065,8 +3092,8 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
|
||||
ntx_path = RF_A;
|
||||
map_b = 0;
|
||||
} else {
|
||||
ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_B;
|
||||
map_b = hal->antenna_tx == RF_AB ? 1 : 0;
|
||||
ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_AB;
|
||||
map_b = ntx_path == RF_AB ? 1 : 0;
|
||||
}
|
||||
|
||||
SET_CMC_TBL_NTX_PATH_EN(skb->data, ntx_path);
|
||||
@@ -4004,8 +4031,9 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_li
|
||||
int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
|
||||
struct rtw89_sta_link *rtwsta_link, bool dis_conn)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
|
||||
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
|
||||
bool is_mld = ieee80211_vif_is_mld(vif);
|
||||
u8 self_role = rtwvif_link->self_role;
|
||||
enum rtw89_fw_sta_type sta_type;
|
||||
u8 net_type = rtwvif_link->net_type;
|
||||
@@ -4013,6 +4041,9 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
|
||||
struct rtw89_h2c_join *h2c;
|
||||
u32 len = sizeof(*h2c);
|
||||
bool format_v1 = false;
|
||||
struct sk_buff *skb;
|
||||
u8 main_mac_id;
|
||||
bool init_ps;
|
||||
int ret;
|
||||
|
||||
if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
|
||||
@@ -4054,8 +4085,28 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
|
||||
h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data;
|
||||
|
||||
sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta_link);
|
||||
init_ps = rtwvif_link != rtw89_get_designated_link(rtwvif_link->rtwvif);
|
||||
|
||||
if (rtwsta_link)
|
||||
main_mac_id = rtw89_sta_get_main_macid(rtwsta_link->rtwsta);
|
||||
else
|
||||
main_mac_id = rtw89_vif_get_main_macid(rtwvif_link->rtwvif);
|
||||
|
||||
h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE) |
|
||||
le32_encode_bits(is_mld, RTW89_H2C_JOININFO_W1_IS_MLD) |
|
||||
le32_encode_bits(main_mac_id, RTW89_H2C_JOININFO_W1_MAIN_MACID) |
|
||||
le32_encode_bits(RTW89_H2C_JOININFO_MLO_MODE_MLSR,
|
||||
RTW89_H2C_JOININFO_W1_MLO_MODE) |
|
||||
le32_encode_bits(0, RTW89_H2C_JOININFO_W1_EMLSR_CAB) |
|
||||
le32_encode_bits(0, RTW89_H2C_JOININFO_W1_NSTR_EN) |
|
||||
le32_encode_bits(init_ps, RTW89_H2C_JOININFO_W1_INIT_PWR_STATE) |
|
||||
le32_encode_bits(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US,
|
||||
RTW89_H2C_JOININFO_W1_EMLSR_PADDING) |
|
||||
le32_encode_bits(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US,
|
||||
RTW89_H2C_JOININFO_W1_EMLSR_TRANS_DELAY) |
|
||||
le32_encode_bits(0, RTW89_H2C_JOININFO_W2_MACID_EXT) |
|
||||
le32_encode_bits(0, RTW89_H2C_JOININFO_W2_MAIN_MACID_EXT);
|
||||
|
||||
h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE);
|
||||
h2c_v1->w2 = 0;
|
||||
|
||||
done:
|
||||
@@ -4339,6 +4390,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_h2c_bcnfltr *h2c;
|
||||
u32 len = sizeof(*h2c);
|
||||
struct sk_buff *skb;
|
||||
u8 max_cnt, cnt;
|
||||
int ret;
|
||||
|
||||
if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
|
||||
@@ -4367,12 +4419,20 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
|
||||
skb_put(skb, len);
|
||||
h2c = (struct rtw89_h2c_bcnfltr *)skb->data;
|
||||
|
||||
if (RTW89_CHK_FW_FEATURE(BEACON_LOSS_COUNT_V1, &rtwdev->fw))
|
||||
max_cnt = BIT(7) - 1;
|
||||
else
|
||||
max_cnt = BIT(4) - 1;
|
||||
|
||||
cnt = min(RTW89_BCN_LOSS_CNT, max_cnt);
|
||||
|
||||
h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) |
|
||||
le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) |
|
||||
le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) |
|
||||
le32_encode_bits(RTW89_BCN_FLTR_OFFLOAD_MODE_DEFAULT,
|
||||
RTW89_H2C_BCNFLTR_W0_MODE) |
|
||||
le32_encode_bits(RTW89_BCN_LOSS_CNT, RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT) |
|
||||
le32_encode_bits(cnt >> 4, RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT_H3) |
|
||||
le32_encode_bits(cnt & 0xf, RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT_L4) |
|
||||
le32_encode_bits(hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) |
|
||||
le32_encode_bits(thold + MAX_RSSI,
|
||||
RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) |
|
||||
@@ -5298,12 +5358,12 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
|
||||
}
|
||||
|
||||
static
|
||||
int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
|
||||
struct list_head *chan_list)
|
||||
int rtw89_fw_h2c_scan_list_offload_ax(struct rtw89_dev *rtwdev, int ch_num,
|
||||
struct list_head *chan_list)
|
||||
{
|
||||
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
|
||||
struct rtw89_h2c_chinfo_elem *elem;
|
||||
struct rtw89_mac_chinfo *ch_info;
|
||||
struct rtw89_mac_chinfo_ax *ch_info;
|
||||
struct rtw89_h2c_chinfo *h2c;
|
||||
struct sk_buff *skb;
|
||||
unsigned int cond;
|
||||
@@ -5477,7 +5537,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RTW89_SCAN_DELAY_TSF_UNIT 104800
|
||||
#define RTW89_SCAN_DELAY_TSF_UNIT 1000000
|
||||
int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_scan_option *option,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
@@ -5741,7 +5801,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
|
||||
RTW89_H2C_SCANOFLD_BE_OPCH_W2_PKTS_CTRL) |
|
||||
le32_encode_bits(0,
|
||||
RTW89_H2C_SCANOFLD_BE_OPCH_W2_SW_DEF) |
|
||||
le32_encode_bits(2,
|
||||
le32_encode_bits(rtw89_is_mlo_1_1(rtwdev) ? 1 : 2,
|
||||
RTW89_H2C_SCANOFLD_BE_OPCH_W2_SS);
|
||||
|
||||
opch->w3 = le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
|
||||
@@ -6525,7 +6585,7 @@ void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev)
|
||||
rtw89_fw_prog_cnt_dump(rtwdev);
|
||||
}
|
||||
|
||||
static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_hw_scan_release_pkt_list(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
|
||||
struct rtw89_pktofld_info *info, *tmp;
|
||||
@@ -6544,6 +6604,23 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_hw_scan_cleanup(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
|
||||
mac->free_chan_list(rtwdev);
|
||||
rtw89_hw_scan_release_pkt_list(rtwdev);
|
||||
|
||||
rtwvif->scan_req = NULL;
|
||||
rtwvif->scan_ies = NULL;
|
||||
scan_info->scanning_vif = NULL;
|
||||
scan_info->abort = false;
|
||||
scan_info->connected = false;
|
||||
}
|
||||
|
||||
static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct rtw89_pktofld_info *info,
|
||||
@@ -6612,7 +6689,8 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
@@ -6621,7 +6699,7 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr,
|
||||
skb = ieee80211_probereq_get(rtwdev->hw, mac_addr,
|
||||
req->ssids[i].ssid,
|
||||
req->ssids[i].ssid_len,
|
||||
req->ie_len);
|
||||
@@ -6638,10 +6716,10 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_scan_ies *ies,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct rtw89_mac_chinfo *ch_info)
|
||||
static int rtw89_update_6ghz_rnr_chan_ax(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_scan_ies *ies,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct rtw89_mac_chinfo_ax *ch_info)
|
||||
{
|
||||
struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
|
||||
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
|
||||
@@ -6713,7 +6791,7 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
|
||||
|
||||
static void rtw89_pno_scan_add_chan_ax(struct rtw89_dev *rtwdev,
|
||||
int chan_type, int ssid_num,
|
||||
struct rtw89_mac_chinfo *ch_info)
|
||||
struct rtw89_mac_chinfo_ax *ch_info)
|
||||
{
|
||||
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
|
||||
struct rtw89_pktofld_info *info;
|
||||
@@ -6761,9 +6839,9 @@ static void rtw89_pno_scan_add_chan_ax(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
|
||||
int ssid_num,
|
||||
struct rtw89_mac_chinfo *ch_info)
|
||||
static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type,
|
||||
int ssid_num,
|
||||
struct rtw89_mac_chinfo_ax *ch_info)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
|
||||
@@ -6794,7 +6872,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
|
||||
}
|
||||
}
|
||||
|
||||
ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info);
|
||||
ret = rtw89_update_6ghz_rnr_chan_ax(rtwdev, ies, req, ch_info);
|
||||
if (ret)
|
||||
rtw89_warn(rtwdev, "RNR fails: %d\n", ret);
|
||||
|
||||
@@ -6950,7 +7028,7 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
{
|
||||
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
|
||||
struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config;
|
||||
struct rtw89_mac_chinfo *ch_info, *tmp;
|
||||
struct rtw89_mac_chinfo_ax *ch_info, *tmp;
|
||||
struct ieee80211_channel *channel;
|
||||
struct list_head chan_list;
|
||||
int list_len;
|
||||
@@ -6984,7 +7062,7 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
rtw89_pno_scan_add_chan_ax(rtwdev, type, nd_config->n_match_sets, ch_info);
|
||||
list_add_tail(&ch_info->list, &chan_list);
|
||||
}
|
||||
ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
|
||||
ret = rtw89_fw_h2c_scan_list_offload_ax(rtwdev, list_len, &chan_list);
|
||||
|
||||
out:
|
||||
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
|
||||
@@ -6995,24 +7073,24 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected)
|
||||
int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
struct rtw89_mac_chinfo *ch_info, *tmp;
|
||||
struct rtw89_mac_chinfo_ax *ch_info, *tmp;
|
||||
struct ieee80211_channel *channel;
|
||||
struct list_head chan_list;
|
||||
bool random_seq = req->flags & NL80211_SCAN_FLAG_RANDOM_SN;
|
||||
int list_len, off_chan_time = 0;
|
||||
enum rtw89_chan_type type;
|
||||
int ret = 0;
|
||||
int off_chan_time = 0;
|
||||
int ret;
|
||||
u32 idx;
|
||||
|
||||
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_AX;
|
||||
idx++, list_len++) {
|
||||
|
||||
for (idx = 0; idx < req->n_channels; idx++) {
|
||||
channel = req->channels[idx];
|
||||
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
|
||||
if (!ch_info) {
|
||||
@@ -7039,9 +7117,9 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
type = RTW89_CHAN_DFS;
|
||||
else
|
||||
type = RTW89_CHAN_ACTIVE;
|
||||
rtw89_hw_scan_add_chan(rtwdev, type, req->n_ssids, ch_info);
|
||||
rtw89_hw_scan_add_chan_ax(rtwdev, type, req->n_ssids, ch_info);
|
||||
|
||||
if (connected &&
|
||||
if (scan_info->connected &&
|
||||
off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME) {
|
||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
@@ -7053,16 +7131,16 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
type = RTW89_CHAN_OPERATE;
|
||||
tmp->period = req->duration_mandatory ?
|
||||
req->duration : RTW89_CHANNEL_TIME;
|
||||
rtw89_hw_scan_add_chan(rtwdev, type, 0, tmp);
|
||||
rtw89_hw_scan_add_chan_ax(rtwdev, type, 0, tmp);
|
||||
list_add_tail(&tmp->list, &chan_list);
|
||||
off_chan_time = 0;
|
||||
list_len++;
|
||||
}
|
||||
list_add_tail(&ch_info->list, &chan_list);
|
||||
off_chan_time += ch_info->period;
|
||||
}
|
||||
rtwdev->scan_info.last_chan_idx = idx;
|
||||
ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
|
||||
|
||||
list_splice_tail(&chan_list, &scan_info->chan_list);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
|
||||
@@ -7073,6 +7151,46 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw89_hw_scan_free_chan_list_ax(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_mac_chinfo_ax *ch_info, *tmp;
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &scan_info->chan_list, list) {
|
||||
list_del(&ch_info->list);
|
||||
kfree(ch_info);
|
||||
}
|
||||
}
|
||||
|
||||
int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_mac_chinfo_ax *ch_info, *tmp;
|
||||
unsigned int list_len = 0;
|
||||
struct list_head list;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&list);
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &scan_info->chan_list, list) {
|
||||
list_move_tail(&ch_info->list, &list);
|
||||
|
||||
list_len++;
|
||||
if (list_len == RTW89_SCAN_LIST_LIMIT_AX)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = rtw89_fw_h2c_scan_list_offload_ax(rtwdev, list_len, &list);
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &list, list) {
|
||||
list_del(&ch_info->list);
|
||||
kfree(ch_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
@@ -7126,25 +7244,24 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected)
|
||||
int rtw89_hw_scan_prep_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
struct rtw89_mac_chinfo_be *ch_info, *tmp;
|
||||
struct ieee80211_channel *channel;
|
||||
struct list_head chan_list;
|
||||
enum rtw89_chan_type type;
|
||||
int list_len, ret;
|
||||
bool random_seq;
|
||||
int ret;
|
||||
u32 idx;
|
||||
|
||||
random_seq = !!(req->flags & NL80211_SCAN_FLAG_RANDOM_SN);
|
||||
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_BE;
|
||||
idx++, list_len++) {
|
||||
for (idx = 0; idx < req->n_channels; idx++) {
|
||||
channel = req->channels[idx];
|
||||
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
|
||||
if (!ch_info) {
|
||||
@@ -7174,9 +7291,8 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
list_add_tail(&ch_info->list, &chan_list);
|
||||
}
|
||||
|
||||
rtwdev->scan_info.last_chan_idx = idx;
|
||||
ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list,
|
||||
rtwvif_link);
|
||||
list_splice_tail(&chan_list, &scan_info->chan_list);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
|
||||
@@ -7187,51 +7303,182 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw89_hw_scan_free_chan_list_be(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_mac_chinfo_be *ch_info, *tmp;
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &scan_info->chan_list, list) {
|
||||
list_del(&ch_info->list);
|
||||
kfree(ch_info);
|
||||
}
|
||||
}
|
||||
|
||||
int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_mac_chinfo_be *ch_info, *tmp;
|
||||
unsigned int list_len = 0;
|
||||
struct list_head list;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&list);
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &scan_info->chan_list, list) {
|
||||
list_move_tail(&ch_info->list, &list);
|
||||
|
||||
list_len++;
|
||||
if (list_len == RTW89_SCAN_LIST_LIMIT_BE)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &list,
|
||||
rtwvif_link);
|
||||
|
||||
list_for_each_entry_safe(ch_info, tmp, &list, list) {
|
||||
list_del(&ch_info->list);
|
||||
kfree(ch_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected)
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
int ret;
|
||||
|
||||
ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link);
|
||||
ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link, mac_addr);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "Update probe request failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = mac->add_chan_list(rtwdev, rtwvif_link, connected);
|
||||
ret = mac->prep_chan_list(rtwdev, rtwvif_link);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct ieee80211_scan_request *scan_req)
|
||||
static void rtw89_hw_scan_update_link_beacon_noa(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
u16 tu)
|
||||
{
|
||||
struct ieee80211_p2p_noa_desc noa_desc = {};
|
||||
u64 tsf;
|
||||
int ret;
|
||||
|
||||
ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
|
||||
if (ret) {
|
||||
rtw89_warn(rtwdev, "%s: failed to get tsf\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
noa_desc.start_time = cpu_to_le32(tsf);
|
||||
noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(tu));
|
||||
noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(tu));
|
||||
noa_desc.count = 1;
|
||||
|
||||
rtw89_p2p_noa_renew(rtwvif_link);
|
||||
rtw89_p2p_noa_append(rtwvif_link, &noa_desc);
|
||||
rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link);
|
||||
}
|
||||
|
||||
static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev,
|
||||
const struct cfg80211_scan_request *req)
|
||||
{
|
||||
const struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
|
||||
const struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_mac_chinfo_ax *chinfo_ax;
|
||||
struct rtw89_mac_chinfo_be *chinfo_be;
|
||||
struct rtw89_vif_link *rtwvif_link;
|
||||
struct list_head *pos, *tmp;
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
u16 tu = 0;
|
||||
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
list_for_each_safe(pos, tmp, &scan_info->chan_list) {
|
||||
switch (chip->chip_gen) {
|
||||
case RTW89_CHIP_AX:
|
||||
chinfo_ax = list_entry(pos, typeof(*chinfo_ax), list);
|
||||
tu += chinfo_ax->period;
|
||||
break;
|
||||
case RTW89_CHIP_BE:
|
||||
chinfo_be = list_entry(pos, typeof(*chinfo_be), list);
|
||||
tu += chinfo_be->period;
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev, "%s: invalid chip gen %d\n",
|
||||
__func__, chip->chip_gen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(tu == 0)) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
|
||||
"%s: cannot estimate needed TU\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(rtwvif, &mgnt->active_list, mgnt_entry) {
|
||||
unsigned int link_id;
|
||||
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
if (vif->type != NL80211_IFTYPE_AP || !vif->p2p)
|
||||
continue;
|
||||
|
||||
rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
|
||||
rtw89_hw_scan_update_link_beacon_noa(rtwdev, rtwvif_link, tu);
|
||||
}
|
||||
}
|
||||
|
||||
int rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct ieee80211_scan_request *scan_req)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev);
|
||||
struct cfg80211_scan_request *req = &scan_req->req;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
|
||||
rtwvif_link->chanctx_idx);
|
||||
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
|
||||
struct rtw89_chanctx_pause_parm pause_parm = {
|
||||
.rsn = RTW89_CHANCTX_PAUSE_REASON_HW_SCAN,
|
||||
.trigger = rtwvif_link,
|
||||
};
|
||||
u32 rx_fltr = rtwdev->hal.rx_fltr;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
/* clone op and keep it during scan */
|
||||
rtwdev->scan_info.op_chan = *chan;
|
||||
|
||||
rtwdev->scan_info.connected = rtw89_is_any_vif_connected_or_connecting(rtwdev);
|
||||
rtwdev->scan_info.scanning_vif = rtwvif_link;
|
||||
rtwdev->scan_info.last_chan_idx = 0;
|
||||
rtwdev->scan_info.abort = false;
|
||||
rtwvif->scan_ies = &scan_req->ies;
|
||||
rtwvif->scan_req = req;
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false);
|
||||
|
||||
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
|
||||
get_random_mask_addr(mac_addr, req->mac_addr,
|
||||
req->mac_addr_mask);
|
||||
else
|
||||
ether_addr_copy(mac_addr, rtwvif_link->mac_addr);
|
||||
|
||||
ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, mac_addr);
|
||||
if (ret) {
|
||||
rtw89_hw_scan_cleanup(rtwdev, rtwvif_link);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false);
|
||||
|
||||
rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true);
|
||||
|
||||
rx_fltr &= ~B_AX_A_BCN_CHK_EN;
|
||||
@@ -7241,7 +7488,12 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
|
||||
reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr);
|
||||
|
||||
rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
|
||||
rtw89_chanctx_pause(rtwdev, &pause_parm);
|
||||
|
||||
if (mode == RTW89_ENTITY_MODE_MCC)
|
||||
rtw89_hw_scan_update_beacon_noa(rtwdev, req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rtw89_hw_scan_complete_cb_data {
|
||||
@@ -7252,20 +7504,16 @@ struct rtw89_hw_scan_complete_cb_data {
|
||||
static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data)
|
||||
{
|
||||
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_hw_scan_complete_cb_data *cb_data = data;
|
||||
struct rtw89_vif_link *rtwvif_link = cb_data->rtwvif_link;
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = cb_data->aborted,
|
||||
};
|
||||
struct rtw89_vif *rtwvif;
|
||||
u32 reg;
|
||||
|
||||
if (!rtwvif_link)
|
||||
return -EINVAL;
|
||||
|
||||
rtwvif = rtwvif_link->rtwvif;
|
||||
|
||||
reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr);
|
||||
|
||||
@@ -7275,12 +7523,7 @@ static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data)
|
||||
rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true);
|
||||
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
|
||||
|
||||
rtw89_release_pkt_list(rtwdev);
|
||||
rtwvif->scan_req = NULL;
|
||||
rtwvif->scan_ies = NULL;
|
||||
scan_info->last_chan_idx = 0;
|
||||
scan_info->scanning_vif = NULL;
|
||||
scan_info->abort = false;
|
||||
rtw89_hw_scan_cleanup(rtwdev, rtwvif_link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -7355,11 +7598,11 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
|
||||
if (!rtwvif_link)
|
||||
return -EINVAL;
|
||||
|
||||
connected = rtw89_is_any_vif_connected_or_connecting(rtwdev);
|
||||
connected = rtwdev->scan_info.connected;
|
||||
opt.enable = enable;
|
||||
opt.target_ch_mode = connected;
|
||||
if (enable) {
|
||||
ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, connected);
|
||||
ret = mac->add_chan_list(rtwdev, rtwvif_link);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@@ -8719,6 +8962,47 @@ int rtw89_fw_h2c_ap_info_refcount(struct rtw89_dev *rtwdev, bool en)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw89_fw_h2c_mlo_link_cfg(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
|
||||
bool enable)
|
||||
{
|
||||
struct rtw89_wait_info *wait = &rtwdev->mlo.wait;
|
||||
struct rtw89_h2c_mlo_link_cfg *h2c;
|
||||
u8 mac_id = rtwvif_link->mac_id;
|
||||
u32 len = sizeof(*h2c);
|
||||
struct sk_buff *skb;
|
||||
unsigned int cond;
|
||||
int ret;
|
||||
|
||||
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
|
||||
if (!skb) {
|
||||
rtw89_err(rtwdev, "failed to alloc skb for mlo link cfg\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb_put(skb, len);
|
||||
h2c = (struct rtw89_h2c_mlo_link_cfg *)skb->data;
|
||||
|
||||
h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_MLO_LINK_CFG_W0_MACID) |
|
||||
le32_encode_bits(enable, RTW89_H2C_MLO_LINK_CFG_W0_OPTION);
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_MAC,
|
||||
H2C_CL_MLO,
|
||||
H2C_FUNC_MLO_LINK_CFG, 0, 0,
|
||||
len);
|
||||
|
||||
cond = RTW89_MLO_WAIT_COND(mac_id, H2C_FUNC_MLO_LINK_CFG);
|
||||
|
||||
ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "mlo link cfg (%s link id %u) failed: %d\n",
|
||||
str_enable_disable(enable), rtwvif_link->link_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __fw_txpwr_entry_zero_ext(const void *ext_ptr, u8 ext_len)
|
||||
{
|
||||
static const u8 zeros[U8_MAX] = {};
|
||||
@@ -9106,6 +9390,26 @@ void rtw89_fw_load_tx_shape_lmt_ru(struct rtw89_tx_shape_lmt_ru_data *data)
|
||||
}
|
||||
}
|
||||
|
||||
static bool rtw89_fw_has_da_txpwr_table(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_rfe_parms *parms)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->support_bands & BIT(NL80211_BAND_2GHZ) &&
|
||||
!(parms->rule_da_2ghz.lmt && parms->rule_da_2ghz.lmt_ru))
|
||||
return false;
|
||||
|
||||
if (chip->support_bands & BIT(NL80211_BAND_5GHZ) &&
|
||||
!(parms->rule_da_5ghz.lmt && parms->rule_da_5ghz.lmt_ru))
|
||||
return false;
|
||||
|
||||
if (chip->support_bands & BIT(NL80211_BAND_6GHZ) &&
|
||||
!(parms->rule_da_6ghz.lmt && parms->rule_da_6ghz.lmt_ru))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct rtw89_rfe_parms *
|
||||
rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_rfe_parms *init)
|
||||
@@ -9142,6 +9446,21 @@ rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
|
||||
parms->rule_6ghz.lmt = &rfe_data->lmt_6ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_2ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_2ghz(&rfe_data->da_lmt_2ghz);
|
||||
parms->rule_da_2ghz.lmt = &rfe_data->da_lmt_2ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_5ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_5ghz(&rfe_data->da_lmt_5ghz);
|
||||
parms->rule_da_5ghz.lmt = &rfe_data->da_lmt_5ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_6ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_6ghz(&rfe_data->da_lmt_6ghz);
|
||||
parms->rule_da_6ghz.lmt = &rfe_data->da_lmt_6ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->lmt_ru_2ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_ru_2ghz(&rfe_data->lmt_ru_2ghz);
|
||||
parms->rule_2ghz.lmt_ru = &rfe_data->lmt_ru_2ghz.v;
|
||||
@@ -9157,6 +9476,21 @@ rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
|
||||
parms->rule_6ghz.lmt_ru = &rfe_data->lmt_ru_6ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_2ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_ru_2ghz(&rfe_data->da_lmt_ru_2ghz);
|
||||
parms->rule_da_2ghz.lmt_ru = &rfe_data->da_lmt_ru_2ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_5ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_ru_5ghz(&rfe_data->da_lmt_ru_5ghz);
|
||||
parms->rule_da_5ghz.lmt_ru = &rfe_data->da_lmt_ru_5ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_6ghz.conf)) {
|
||||
rtw89_fw_load_txpwr_lmt_ru_6ghz(&rfe_data->da_lmt_ru_6ghz);
|
||||
parms->rule_da_6ghz.lmt_ru = &rfe_data->da_lmt_ru_6ghz.v;
|
||||
}
|
||||
|
||||
if (rtw89_txpwr_conf_valid(&rfe_data->tx_shape_lmt.conf)) {
|
||||
rtw89_fw_load_tx_shape_lmt(&rfe_data->tx_shape_lmt);
|
||||
parms->tx_shape.lmt = &rfe_data->tx_shape_lmt.v;
|
||||
@@ -9167,5 +9501,7 @@ rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
|
||||
parms->tx_shape.lmt_ru = &rfe_data->tx_shape_lmt_ru.v;
|
||||
}
|
||||
|
||||
parms->has_da = rtw89_fw_has_da_txpwr_table(rtwdev, parms);
|
||||
|
||||
return parms;
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ enum rtw89_fw_log_comp {
|
||||
RTW89_FW_LOG_COMP_TWT,
|
||||
RTW89_FW_LOG_COMP_RF,
|
||||
RTW89_FW_LOG_COMP_MCC = 20,
|
||||
RTW89_FW_LOG_COMP_MLO = 26,
|
||||
RTW89_FW_LOG_COMP_SCAN = 28,
|
||||
};
|
||||
|
||||
@@ -333,9 +334,9 @@ struct rtw89_fw_macid_pause_sleep_grp {
|
||||
#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
|
||||
#define RTW89_BCN_LOSS_CNT 60
|
||||
|
||||
struct rtw89_mac_chinfo {
|
||||
struct rtw89_mac_chinfo_ax {
|
||||
u8 period;
|
||||
u8 dwell_time;
|
||||
u8 central_ch;
|
||||
@@ -1636,6 +1637,8 @@ struct rtw89_h2c_join_v1 {
|
||||
#define RTW89_H2C_JOININFO_W1_IS_MLD BIT(3)
|
||||
#define RTW89_H2C_JOININFO_W1_MAIN_MACID GENMASK(11, 4)
|
||||
#define RTW89_H2C_JOININFO_W1_MLO_MODE BIT(12)
|
||||
#define RTW89_H2C_JOININFO_MLO_MODE_MLMR 0
|
||||
#define RTW89_H2C_JOININFO_MLO_MODE_MLSR 1
|
||||
#define RTW89_H2C_JOININFO_W1_EMLSR_CAB BIT(13)
|
||||
#define RTW89_H2C_JOININFO_W1_NSTR_EN BIT(14)
|
||||
#define RTW89_H2C_JOININFO_W1_INIT_PWR_STATE BIT(15)
|
||||
@@ -2863,6 +2866,13 @@ struct rtw89_h2c_fwips {
|
||||
#define RTW89_H2C_FW_IPS_W0_MACID GENMASK(7, 0)
|
||||
#define RTW89_H2C_FW_IPS_W0_ENABLE BIT(8)
|
||||
|
||||
struct rtw89_h2c_mlo_link_cfg {
|
||||
__le32 w0;
|
||||
};
|
||||
|
||||
#define RTW89_H2C_MLO_LINK_CFG_W0_MACID GENMASK(15, 0)
|
||||
#define RTW89_H2C_MLO_LINK_CFG_W0_OPTION GENMASK(19, 16)
|
||||
|
||||
static inline void RTW89_SET_FWCMD_P2P_MACID(void *cmd, u32 val)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)cmd, val, GENMASK(7, 0));
|
||||
@@ -3562,6 +3572,7 @@ struct rtw89_c2h_done_ack {
|
||||
#define RTW89_C2H_DONE_ACK_W2_CLASS GENMASK(7, 2)
|
||||
#define RTW89_C2H_DONE_ACK_W2_FUNC GENMASK(15, 8)
|
||||
#define RTW89_C2H_DONE_ACK_W2_H2C_RETURN GENMASK(23, 16)
|
||||
#define RTW89_C2H_SCAN_DONE_ACK_RETURN GENMASK(5, 0)
|
||||
#define RTW89_C2H_DONE_ACK_W2_H2C_SEQ GENMASK(31, 24)
|
||||
|
||||
#define RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h) \
|
||||
@@ -3620,6 +3631,19 @@ struct rtw89_c2h_ra_rpt {
|
||||
#define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15)
|
||||
#define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16)
|
||||
|
||||
struct rtw89_c2h_fw_scan_rpt {
|
||||
struct rtw89_c2h_hdr hdr;
|
||||
u8 phy_idx;
|
||||
u8 band;
|
||||
u8 center_ch;
|
||||
u8 ofdm_pd_idx; /* in unit of 2 dBm */
|
||||
#define PD_LOWER_BOUND_BASE 102
|
||||
s8 cck_pd_idx;
|
||||
u8 rsvd0;
|
||||
u8 rsvd1;
|
||||
u8 rsvd2;
|
||||
} __packed;
|
||||
|
||||
/* For WiFi 6 chips:
|
||||
* VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS
|
||||
* HT-new: [6:5]: NA, [4:0]: MCS
|
||||
@@ -3717,6 +3741,25 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE)
|
||||
#define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \
|
||||
le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0))
|
||||
|
||||
struct rtw89_c2h_mlo_link_cfg_rpt {
|
||||
struct rtw89_c2h_hdr hdr;
|
||||
__le32 w2;
|
||||
} __packed;
|
||||
|
||||
#define RTW89_C2H_MLO_LINK_CFG_RPT_W2_MACID GENMASK(15, 0)
|
||||
#define RTW89_C2H_MLO_LINK_CFG_RPT_W2_STATUS GENMASK(19, 16)
|
||||
|
||||
enum rtw89_c2h_mlo_link_status {
|
||||
RTW89_C2H_MLO_LINK_CFG_IDLE = 0,
|
||||
RTW89_C2H_MLO_LINK_CFG_DONE = 1,
|
||||
RTW89_C2H_MLO_LINK_CFG_ISSUE_NULL_FAIL = 2,
|
||||
RTW89_C2H_MLO_LINK_CFG_TX_NULL_FAIL = 3,
|
||||
RTW89_C2H_MLO_LINK_CFG_ROLE_NOT_EXIST = 4,
|
||||
RTW89_C2H_MLO_LINK_CFG_NULL_1_TIMEOUT = 5,
|
||||
RTW89_C2H_MLO_LINK_CFG_NULL_0_TIMEOUT = 6,
|
||||
RTW89_C2H_MLO_LINK_CFG_RUNNING = 0xff,
|
||||
};
|
||||
|
||||
struct rtw89_mac_mrc_tsf_rpt {
|
||||
unsigned int num;
|
||||
u64 tsfs[RTW89_MAC_MRC_MAX_REQ_TSF_NUM];
|
||||
@@ -3813,7 +3856,8 @@ struct rtw89_h2c_bcnfltr {
|
||||
#define RTW89_H2C_BCNFLTR_W0_MON_BCN BIT(1)
|
||||
#define RTW89_H2C_BCNFLTR_W0_MON_EN BIT(2)
|
||||
#define RTW89_H2C_BCNFLTR_W0_MODE GENMASK(4, 3)
|
||||
#define RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT GENMASK(11, 8)
|
||||
#define RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT_H3 GENMASK(7, 5)
|
||||
#define RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT_L4 GENMASK(11, 8)
|
||||
#define RTW89_H2C_BCNFLTR_W0_RSSI_HYST GENMASK(15, 12)
|
||||
#define RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD GENMASK(23, 16)
|
||||
#define RTW89_H2C_BCNFLTR_W0_MAC_ID GENMASK(31, 24)
|
||||
@@ -3891,6 +3935,12 @@ enum rtw89_fw_element_id {
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_TRK = 18,
|
||||
RTW89_FW_ELEMENT_ID_RFKLOG_FMT = 19,
|
||||
RTW89_FW_ELEMENT_ID_REGD = 20,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_2GHZ = 21,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_5GHZ = 22,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_6GHZ = 23,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_2GHZ = 24,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ = 25,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26,
|
||||
|
||||
RTW89_FW_ELEMENT_ID_NUM,
|
||||
};
|
||||
@@ -4229,6 +4279,26 @@ enum rtw89_mcc_h2c_func {
|
||||
#define RTW89_MCC_WAIT_COND(group, func) \
|
||||
((group) * NUM_OF_RTW89_MCC_H2C_FUNC + (func))
|
||||
|
||||
/* CLASS 20 - MLO */
|
||||
#define H2C_CL_MLO 0x14
|
||||
enum rtw89_mlo_h2c_func {
|
||||
H2C_FUNC_MLO_TBL_CFG = 0x0,
|
||||
H2C_FUNC_MLO_STA_CFG = 0x1,
|
||||
H2C_FUNC_MLO_TTLM = 0x2,
|
||||
H2C_FUNC_MLO_DM_CFG = 0x3,
|
||||
H2C_FUNC_MLO_EMLSR_STA_CFG = 0x4,
|
||||
H2C_FUNC_MLO_MCMLO_RELINK_DROP = 0x5,
|
||||
H2C_FUNC_MLO_MCMLO_SN_SYNC = 0x6,
|
||||
H2C_FUNC_MLO_RELINK = 0x7,
|
||||
H2C_FUNC_MLO_LINK_CFG = 0x8,
|
||||
H2C_FUNC_MLO_DM_DBG = 0x9,
|
||||
|
||||
NUM_OF_RTW89_MLO_H2C_FUNC,
|
||||
};
|
||||
|
||||
#define RTW89_MLO_WAIT_COND(macid, func) \
|
||||
((macid) * NUM_OF_RTW89_MLO_H2C_FUNC + (func))
|
||||
|
||||
/* CLASS 24 - MRC */
|
||||
#define H2C_CL_MRC 0x18
|
||||
enum rtw89_mrc_h2c_func {
|
||||
@@ -4715,9 +4785,9 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_mac_c2h_info *c2h_info);
|
||||
int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable);
|
||||
void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev);
|
||||
void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
int rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link,
|
||||
bool aborted);
|
||||
@@ -4726,12 +4796,18 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
|
||||
bool enable);
|
||||
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int rtw89_hw_scan_prep_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
void rtw89_hw_scan_free_chan_list_ax(struct rtw89_dev *rtwdev);
|
||||
int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected);
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int rtw89_hw_scan_prep_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
void rtw89_hw_scan_free_chan_list_be(struct rtw89_dev *rtwdev);
|
||||
int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected);
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
|
||||
@@ -4800,6 +4876,8 @@ int rtw89_fw_h2c_mrc_sync(struct rtw89_dev *rtwdev,
|
||||
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);
|
||||
int rtw89_fw_h2c_mlo_link_cfg(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
|
||||
bool enable);
|
||||
|
||||
static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
|
||||
@@ -4631,11 +4631,17 @@ static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev,
|
||||
if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif_link == rtwvif_src)
|
||||
return;
|
||||
|
||||
if (rtwvif_link->rand_tsf_done)
|
||||
goto out;
|
||||
|
||||
/* adjust offset randomly to avoid beacon conflict */
|
||||
offset = offset - offset / 4 + get_random_u32() % (offset / 2);
|
||||
rtw89_mac_port_tsf_sync(rtwdev, rtwvif_link, rtwvif_src,
|
||||
(*n_offset) * offset);
|
||||
|
||||
rtwvif_link->rand_tsf_done = true;
|
||||
|
||||
out:
|
||||
(*n_offset)++;
|
||||
}
|
||||
|
||||
@@ -4866,6 +4872,8 @@ void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev,
|
||||
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link);
|
||||
|
||||
rtwvif_link->rand_tsf_done = false;
|
||||
}
|
||||
|
||||
int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
|
||||
@@ -4899,11 +4907,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;
|
||||
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;
|
||||
u32 report_tsf;
|
||||
u16 chan;
|
||||
int ret;
|
||||
|
||||
@@ -4962,7 +4970,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
||||
return;
|
||||
|
||||
if (rtwvif_link && rtwvif->scan_req &&
|
||||
last_chan < rtwvif->scan_req->n_channels) {
|
||||
!list_empty(&rtwdev->scan_info.chan_list)) {
|
||||
ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
|
||||
if (ret) {
|
||||
rtw89_hw_scan_abort(rtwdev, rtwvif_link);
|
||||
@@ -5017,7 +5025,8 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
|
||||
|
||||
switch (type) {
|
||||
case RTW89_BCN_FLTR_BEACON_LOSS:
|
||||
if (!rtwdev->scanning && !rtwvif->offchan)
|
||||
if (!rtwdev->scanning && !rtwvif->offchan &&
|
||||
!rtwvif_link->noa_once.in_duration)
|
||||
ieee80211_connection_loss(vif);
|
||||
else
|
||||
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
|
||||
@@ -5110,12 +5119,14 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
|
||||
return;
|
||||
case H2C_FUNC_ADD_SCANOFLD_CH:
|
||||
cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
|
||||
h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN;
|
||||
break;
|
||||
case H2C_FUNC_SCANOFLD:
|
||||
cond = RTW89_SCANOFLD_WAIT_COND_START;
|
||||
break;
|
||||
case H2C_FUNC_SCANOFLD_BE:
|
||||
cond = RTW89_SCANOFLD_BE_WAIT_COND_START;
|
||||
h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5398,6 +5409,27 @@ rtw89_mac_c2h_wow_aoac_rpt(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 le
|
||||
rtw89_complete_cond(wait, RTW89_WOW_WAIT_COND_AOAC, &data);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_mac_c2h_mlo_link_cfg_stat(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
|
||||
{
|
||||
const struct rtw89_c2h_mlo_link_cfg_rpt *c2h_rpt;
|
||||
struct rtw89_wait_info *wait = &rtwdev->mlo.wait;
|
||||
struct rtw89_completion_data data = {};
|
||||
unsigned int cond;
|
||||
u16 mac_id;
|
||||
u8 status;
|
||||
|
||||
c2h_rpt = (const struct rtw89_c2h_mlo_link_cfg_rpt *)c2h->data;
|
||||
|
||||
mac_id = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MLO_LINK_CFG_RPT_W2_MACID);
|
||||
status = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MLO_LINK_CFG_RPT_W2_STATUS);
|
||||
|
||||
data.err = status == RTW89_C2H_MLO_LINK_CFG_ROLE_NOT_EXIST ||
|
||||
status == RTW89_C2H_MLO_LINK_CFG_RUNNING;
|
||||
cond = RTW89_MLO_WAIT_COND(mac_id, H2C_FUNC_MLO_LINK_CFG);
|
||||
rtw89_complete_cond(wait, cond, &data);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
|
||||
{
|
||||
@@ -5552,6 +5584,18 @@ void (* const rtw89_mac_c2h_mcc_handler[])(struct rtw89_dev *rtwdev,
|
||||
[RTW89_MAC_C2H_FUNC_MCC_STATUS_RPT] = rtw89_mac_c2h_mcc_status_rpt,
|
||||
};
|
||||
|
||||
static
|
||||
void (* const rtw89_mac_c2h_mlo_handler[])(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *c2h, u32 len) = {
|
||||
[RTW89_MAC_C2H_FUNC_MLO_GET_TBL] = NULL,
|
||||
[RTW89_MAC_C2H_FUNC_MLO_EMLSR_TRANS_DONE] = NULL,
|
||||
[RTW89_MAC_C2H_FUNC_MLO_EMLSR_STA_CFG_DONE] = NULL,
|
||||
[RTW89_MAC_C2H_FUNC_MCMLO_RELINK_RPT] = NULL,
|
||||
[RTW89_MAC_C2H_FUNC_MCMLO_SN_SYNC_RPT] = NULL,
|
||||
[RTW89_MAC_C2H_FUNC_MLO_LINK_CFG_STAT] = rtw89_mac_c2h_mlo_link_cfg_stat,
|
||||
[RTW89_MAC_C2H_FUNC_MLO_DM_DBG_DUMP] = NULL,
|
||||
};
|
||||
|
||||
static
|
||||
void (* const rtw89_mac_c2h_mrc_handler[])(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *c2h, u32 len) = {
|
||||
@@ -5621,6 +5665,8 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
|
||||
}
|
||||
case RTW89_MAC_C2H_CLASS_MCC:
|
||||
return true;
|
||||
case RTW89_MAC_C2H_CLASS_MLO:
|
||||
return true;
|
||||
case RTW89_MAC_C2H_CLASS_MRC:
|
||||
return true;
|
||||
case RTW89_MAC_C2H_CLASS_WOW:
|
||||
@@ -5654,6 +5700,10 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
||||
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MCC)
|
||||
handler = rtw89_mac_c2h_mcc_handler[func];
|
||||
break;
|
||||
case RTW89_MAC_C2H_CLASS_MLO:
|
||||
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MLO)
|
||||
handler = rtw89_mac_c2h_mlo_handler[func];
|
||||
break;
|
||||
case RTW89_MAC_C2H_CLASS_MRC:
|
||||
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MRC)
|
||||
handler = rtw89_mac_c2h_mrc_handler[func];
|
||||
@@ -6889,6 +6939,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
|
||||
|
||||
.is_txq_empty = mac_is_txq_empty_ax,
|
||||
|
||||
.prep_chan_list = rtw89_hw_scan_prep_chan_list_ax,
|
||||
.free_chan_list = rtw89_hw_scan_free_chan_list_ax,
|
||||
.add_chan_list = rtw89_hw_scan_add_chan_list_ax,
|
||||
.add_chan_list_pno = rtw89_pno_scan_add_chan_list_ax,
|
||||
.scan_offload = rtw89_fw_h2c_scan_offload_ax,
|
||||
|
||||
@@ -370,6 +370,7 @@ enum rtw89_mac_mem_sel {
|
||||
RTW89_MAC_MEM_TXD_FIFO_0_V1,
|
||||
RTW89_MAC_MEM_TXD_FIFO_1_V1,
|
||||
RTW89_MAC_MEM_WD_PAGE,
|
||||
RTW89_MAC_MEM_MLD_TBL,
|
||||
|
||||
/* keep last */
|
||||
RTW89_MAC_MEM_NUM,
|
||||
@@ -427,6 +428,18 @@ enum rtw89_mac_c2h_mcc_func {
|
||||
NUM_OF_RTW89_MAC_C2H_FUNC_MCC,
|
||||
};
|
||||
|
||||
enum rtw89_mac_c2h_mlo_func {
|
||||
RTW89_MAC_C2H_FUNC_MLO_GET_TBL = 0x0,
|
||||
RTW89_MAC_C2H_FUNC_MLO_EMLSR_TRANS_DONE = 0x1,
|
||||
RTW89_MAC_C2H_FUNC_MLO_EMLSR_STA_CFG_DONE = 0x2,
|
||||
RTW89_MAC_C2H_FUNC_MCMLO_RELINK_RPT = 0x3,
|
||||
RTW89_MAC_C2H_FUNC_MCMLO_SN_SYNC_RPT = 0x4,
|
||||
RTW89_MAC_C2H_FUNC_MLO_LINK_CFG_STAT = 0x5,
|
||||
RTW89_MAC_C2H_FUNC_MLO_DM_DBG_DUMP = 0x6,
|
||||
|
||||
NUM_OF_RTW89_MAC_C2H_FUNC_MLO,
|
||||
};
|
||||
|
||||
enum rtw89_mac_c2h_mrc_func {
|
||||
RTW89_MAC_C2H_FUNC_MRC_TSF_RPT = 0,
|
||||
RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT = 1,
|
||||
@@ -453,6 +466,7 @@ enum rtw89_mac_c2h_class {
|
||||
RTW89_MAC_C2H_CLASS_WOW = 0x3,
|
||||
RTW89_MAC_C2H_CLASS_MCC = 0x4,
|
||||
RTW89_MAC_C2H_CLASS_FWDBG = 0x5,
|
||||
RTW89_MAC_C2H_CLASS_MLO = 0xc,
|
||||
RTW89_MAC_C2H_CLASS_MRC = 0xe,
|
||||
RTW89_MAC_C2H_CLASS_AP = 0x18,
|
||||
RTW89_MAC_C2H_CLASS_MAX,
|
||||
@@ -1031,8 +1045,11 @@ struct rtw89_mac_gen_def {
|
||||
|
||||
bool (*is_txq_empty)(struct rtw89_dev *rtwdev);
|
||||
|
||||
int (*prep_chan_list)(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
void (*free_chan_list)(struct rtw89_dev *rtwdev);
|
||||
int (*add_chan_list)(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link, bool connected);
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int (*add_chan_list_pno)(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif_link *rtwvif_link);
|
||||
int (*scan_offload)(struct rtw89_dev *rtwdev,
|
||||
|
||||
@@ -114,11 +114,14 @@ static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev,
|
||||
wiphy_work_init(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work);
|
||||
INIT_LIST_HEAD(&rtwvif_link->general_pkt_list);
|
||||
|
||||
rtw89_p2p_noa_once_init(rtwvif_link);
|
||||
|
||||
rtwvif_link->hit_rule = 0;
|
||||
rtwvif_link->bcn_hit_cond = 0;
|
||||
rtwvif_link->chanctx_assigned = false;
|
||||
rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
|
||||
rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
|
||||
rtwvif_link->rand_tsf_done = false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -142,6 +145,8 @@ static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev,
|
||||
|
||||
wiphy_work_cancel(rtwdev->hw->wiphy, &rtwvif_link->update_beacon_work);
|
||||
|
||||
rtw89_p2p_noa_once_deinit(rtwvif_link);
|
||||
|
||||
rtw89_leave_ps_mode(rtwdev);
|
||||
|
||||
rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP);
|
||||
@@ -186,6 +191,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
|
||||
if (!rtw89_rtwvif_in_list(rtwdev, rtwvif)) {
|
||||
list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
|
||||
INIT_LIST_HEAD(&rtwvif->mgnt_entry);
|
||||
INIT_LIST_HEAD(&rtwvif->dlink_pool);
|
||||
}
|
||||
|
||||
ether_addr_copy(rtwvif->mac_addr, vif->addr);
|
||||
@@ -479,6 +485,8 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
|
||||
int i;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
|
||||
rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR;
|
||||
|
||||
/* for station mode, assign the mac_id from itself */
|
||||
macid = rtw89_vif_get_main_macid(rtwvif);
|
||||
} else {
|
||||
@@ -494,6 +502,8 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
|
||||
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
|
||||
rtw89_core_txq_init(rtwdev, sta->txq[i]);
|
||||
|
||||
INIT_LIST_HEAD(&rtwsta->dlink_pool);
|
||||
|
||||
skb_queue_head_init(&rtwsta->roc_queue);
|
||||
bitmap_zero(rtwsta->pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
|
||||
|
||||
@@ -1018,7 +1028,7 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
|
||||
struct rtw89_sta_link *rtwsta_link;
|
||||
|
||||
rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
|
||||
rtwsta_link = rtw89_get_designated_link(rtwsta);
|
||||
if (unlikely(!rtwsta_link))
|
||||
return;
|
||||
|
||||
@@ -1153,12 +1163,14 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw,
|
||||
|
||||
lockdep_assert_wiphy(hw->wiphy);
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n");
|
||||
rtw89_err(rtwdev, "sw scan start: find no designated link\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rtw89_leave_lps(rtwdev);
|
||||
|
||||
rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false);
|
||||
}
|
||||
|
||||
@@ -1171,9 +1183,9 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
|
||||
lockdep_assert_wiphy(hw->wiphy);
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n");
|
||||
rtw89_err(rtwdev, "sw scan complete: find no designated link\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1205,13 +1217,19 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (rtwdev->scanning || rtwvif->offchan)
|
||||
return -EBUSY;
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "hw scan: find no link on HW-0\n");
|
||||
rtw89_err(rtwdev, "hw scan: find no designated link\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
rtw89_hw_scan_start(rtwdev, rtwvif_link, req);
|
||||
rtw89_leave_lps(rtwdev);
|
||||
rtw89_leave_ips_by_hwflags(rtwdev);
|
||||
|
||||
ret = rtw89_hw_scan_start(rtwdev, rtwvif_link, req);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
|
||||
if (ret) {
|
||||
rtw89_hw_scan_abort(rtwdev, rtwvif_link);
|
||||
@@ -1236,9 +1254,9 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
|
||||
if (!rtwdev->scanning)
|
||||
return;
|
||||
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (unlikely(!rtwvif_link)) {
|
||||
rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n");
|
||||
rtw89_err(rtwdev, "cancel hw scan: find no designated link\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ static const u32 rtw89_mac_mem_base_addrs_be[RTW89_MAC_MEM_NUM] = {
|
||||
[RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR_BE,
|
||||
[RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR_BE,
|
||||
[RTW89_MAC_MEM_WD_PAGE] = WD_PAGE_BASE_ADDR_BE,
|
||||
[RTW89_MAC_MEM_MLD_TBL] = MLD_TBL_BASE_ADDR_BE,
|
||||
};
|
||||
|
||||
static const struct rtw89_port_reg rtw89_port_base_be = {
|
||||
@@ -2636,6 +2637,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
|
||||
|
||||
.is_txq_empty = mac_is_txq_empty_be,
|
||||
|
||||
.prep_chan_list = rtw89_hw_scan_prep_chan_list_be,
|
||||
.free_chan_list = rtw89_hw_scan_free_chan_list_be,
|
||||
.add_chan_list = rtw89_hw_scan_add_chan_list_be,
|
||||
.add_chan_list_pno = rtw89_pno_scan_add_chan_list_be,
|
||||
.scan_offload = rtw89_fw_h2c_scan_offload_be,
|
||||
|
||||
@@ -228,7 +228,7 @@ int rtw89_pci_sync_skb_for_device_and_validate_rx_info(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
|
||||
int rx_tag_retry = 100;
|
||||
int rx_tag_retry = 1000;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
@@ -3105,17 +3105,26 @@ static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
|
||||
static int rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev, bool force)
|
||||
{
|
||||
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
|
||||
struct pci_dev *pdev = rtwpci->pdev;
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (!rtwpci->enable_dac)
|
||||
return;
|
||||
if (!rtwpci->enable_dac && !force)
|
||||
return 0;
|
||||
|
||||
if (!rtw89_pci_chip_is_manual_dac(rtwdev))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS);
|
||||
/* Configure DAC only via PCI config API, not DBI interfaces */
|
||||
ret = pci_read_config_byte(pdev, RTW89_PCIE_L1_CTRL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val |= RTW89_PCIE_BIT_EN_64BITS;
|
||||
return pci_write_config_byte(pdev, RTW89_PCIE_L1_CTRL, val);
|
||||
}
|
||||
|
||||
static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
|
||||
@@ -3133,13 +3142,16 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
if (!rtw89_pci_is_dac_compatible_bridge(rtwdev))
|
||||
goto no_dac;
|
||||
goto try_dac_done;
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
|
||||
if (!ret) {
|
||||
rtwpci->enable_dac = true;
|
||||
rtw89_pci_cfg_dac(rtwdev);
|
||||
} else {
|
||||
ret = rtw89_pci_cfg_dac(rtwdev, true);
|
||||
if (!ret) {
|
||||
rtwpci->enable_dac = true;
|
||||
goto try_dac_done;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev,
|
||||
@@ -3147,7 +3159,7 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
|
||||
goto err_release_regions;
|
||||
}
|
||||
}
|
||||
no_dac:
|
||||
try_dac_done:
|
||||
|
||||
resource_len = pci_resource_len(pdev, bar_id);
|
||||
rtwpci->mmap = pci_iomap(pdev, bar_id, resource_len);
|
||||
@@ -4302,7 +4314,7 @@ static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev)
|
||||
void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume)
|
||||
{
|
||||
if (resume)
|
||||
rtw89_pci_cfg_dac(rtwdev);
|
||||
rtw89_pci_cfg_dac(rtwdev, false);
|
||||
|
||||
rtw89_pci_disable_eq(rtwdev);
|
||||
rtw89_pci_filter_out(rtwdev);
|
||||
|
||||
@@ -2034,19 +2034,10 @@ static s8 rtw89_phy_ant_gain_query(struct rtw89_dev *rtwdev,
|
||||
ant_gain->offset[path][subband_h]);
|
||||
}
|
||||
|
||||
static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 center_freq)
|
||||
static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, 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->block_country || !(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);
|
||||
|
||||
@@ -2056,18 +2047,31 @@ static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 cente
|
||||
return max(offset_patha, offset_pathb);
|
||||
}
|
||||
|
||||
static bool rtw89_can_apply_ant_gain(struct rtw89_dev *rtwdev, u8 band)
|
||||
{
|
||||
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
|
||||
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);
|
||||
|
||||
if (!chip->support_ant_gain)
|
||||
return false;
|
||||
|
||||
if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
|
||||
return false;
|
||||
|
||||
if (!rfe_parms->has_da)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
return 0;
|
||||
|
||||
if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
|
||||
if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type))
|
||||
return 0;
|
||||
|
||||
if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
|
||||
@@ -2083,14 +2087,10 @@ EXPORT_SYMBOL(rtw89_phy_ant_gain_pwr_offset);
|
||||
int rtw89_print_ant_gain(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
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);
|
||||
char *p = buf, *end = buf + bufsz;
|
||||
s8 offset_patha, offset_pathb;
|
||||
|
||||
if (!(chip->support_ant_gain && (ant_gain->regd_enabled & BIT(regd))) ||
|
||||
ant_gain->block_country) {
|
||||
if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type)) {
|
||||
p += scnprintf(p, end - p, "no DAG is applied\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -2255,20 +2255,31 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
|
||||
{
|
||||
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
|
||||
const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
|
||||
const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
|
||||
const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
|
||||
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
|
||||
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
|
||||
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
|
||||
u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
|
||||
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
|
||||
s8 lmt = 0, da_lmt = S8_MAX, sar, offset = 0;
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
u8 reg6 = regulatory->reg_6ghz_power;
|
||||
s8 lmt = 0, sar, offset;
|
||||
struct rtw89_sar_parm sar_parm = {
|
||||
.center_freq = freq,
|
||||
.ntx = ntx,
|
||||
};
|
||||
s8 cstr;
|
||||
|
||||
switch (band) {
|
||||
case RTW89_BAND_2G:
|
||||
if (has_ant_gain)
|
||||
da_lmt = (*rule_da_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
|
||||
|
||||
lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
|
||||
if (lmt)
|
||||
break;
|
||||
@@ -2276,6 +2287,9 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
|
||||
break;
|
||||
case RTW89_BAND_5G:
|
||||
if (has_ant_gain)
|
||||
da_lmt = (*rule_da_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
|
||||
|
||||
lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
|
||||
if (lmt)
|
||||
break;
|
||||
@@ -2283,6 +2297,9 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
|
||||
break;
|
||||
case RTW89_BAND_6G:
|
||||
if (has_ant_gain)
|
||||
da_lmt = (*rule_da_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
|
||||
|
||||
lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
|
||||
if (lmt)
|
||||
break;
|
||||
@@ -2296,9 +2313,12 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
da_lmt = da_lmt ?: S8_MAX;
|
||||
if (da_lmt != S8_MAX)
|
||||
offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
|
||||
|
||||
lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt + offset, da_lmt));
|
||||
sar = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
|
||||
|
||||
return min3(lmt, sar, cstr);
|
||||
@@ -2515,20 +2535,31 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
|
||||
u8 ru, u8 ntx, u8 ch)
|
||||
{
|
||||
const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
|
||||
const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
|
||||
const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
|
||||
const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
|
||||
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
|
||||
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
|
||||
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
|
||||
u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
|
||||
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
|
||||
s8 lmt_ru = 0, da_lmt_ru = S8_MAX, sar, offset = 0;
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
u8 reg6 = regulatory->reg_6ghz_power;
|
||||
s8 lmt_ru = 0, sar, offset;
|
||||
struct rtw89_sar_parm sar_parm = {
|
||||
.center_freq = freq,
|
||||
.ntx = ntx,
|
||||
};
|
||||
s8 cstr;
|
||||
|
||||
switch (band) {
|
||||
case RTW89_BAND_2G:
|
||||
if (has_ant_gain)
|
||||
da_lmt_ru = (*rule_da_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
|
||||
|
||||
lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
|
||||
if (lmt_ru)
|
||||
break;
|
||||
@@ -2536,6 +2567,9 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
|
||||
lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
|
||||
break;
|
||||
case RTW89_BAND_5G:
|
||||
if (has_ant_gain)
|
||||
da_lmt_ru = (*rule_da_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
|
||||
|
||||
lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
|
||||
if (lmt_ru)
|
||||
break;
|
||||
@@ -2543,6 +2577,9 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
|
||||
lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
|
||||
break;
|
||||
case RTW89_BAND_6G:
|
||||
if (has_ant_gain)
|
||||
da_lmt_ru = (*rule_da_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
|
||||
|
||||
lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
|
||||
if (lmt_ru)
|
||||
break;
|
||||
@@ -2556,9 +2593,12 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
da_lmt_ru = da_lmt_ru ?: S8_MAX;
|
||||
if (da_lmt_ru != S8_MAX)
|
||||
offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
|
||||
|
||||
lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt_ru + offset, da_lmt_ru));
|
||||
sar = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
|
||||
|
||||
return min3(lmt_ru, sar, cstr);
|
||||
@@ -3015,6 +3055,35 @@ void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev,
|
||||
[RTW89_PHY_C2H_FUNC_TXSTS] = NULL,
|
||||
};
|
||||
|
||||
static void
|
||||
rtw89_phy_c2h_lowrt_rty(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_phy_c2h_fw_scan_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
|
||||
{
|
||||
const struct rtw89_c2h_fw_scan_rpt *c2h_rpt =
|
||||
(const struct rtw89_c2h_fw_scan_rpt *)c2h->data;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_DIG,
|
||||
"%s: band: %u, op_chan: %u, PD_low_bd(ofdm, cck): (-%d, %d), phy_idx: %u\n",
|
||||
__func__, c2h_rpt->band, c2h_rpt->center_ch,
|
||||
PD_LOWER_BOUND_BASE - (c2h_rpt->ofdm_pd_idx << 1),
|
||||
c2h_rpt->cck_pd_idx, c2h_rpt->phy_idx);
|
||||
}
|
||||
|
||||
static
|
||||
void (* const rtw89_phy_c2h_dm_handler[])(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *c2h, u32 len) = {
|
||||
[RTW89_PHY_C2H_DM_FUNC_FW_TEST] = NULL,
|
||||
[RTW89_PHY_C2H_DM_FUNC_FW_TRIG_TX_RPT] = NULL,
|
||||
[RTW89_PHY_C2H_DM_FUNC_SIGB] = NULL,
|
||||
[RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY] = rtw89_phy_c2h_lowrt_rty,
|
||||
[RTW89_PHY_C2H_DM_FUNC_MCC_DIG] = NULL,
|
||||
[RTW89_PHY_C2H_DM_FUNC_FW_SCAN] = rtw89_phy_c2h_fw_scan_rpt,
|
||||
};
|
||||
|
||||
static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_c2h_rfk_log_func func,
|
||||
void *content, u16 len)
|
||||
@@ -3550,9 +3619,9 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
||||
handler = rtw89_phy_c2h_rfk_report_handler[func];
|
||||
break;
|
||||
case RTW89_PHY_C2H_CLASS_DM:
|
||||
if (func == RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY)
|
||||
return;
|
||||
fallthrough;
|
||||
if (func < ARRAY_SIZE(rtw89_phy_c2h_dm_handler))
|
||||
handler = rtw89_phy_c2h_dm_handler[func];
|
||||
break;
|
||||
default:
|
||||
rtw89_info(rtwdev, "PHY c2h class %d not support\n", class);
|
||||
return;
|
||||
|
||||
@@ -164,6 +164,7 @@ enum rtw89_phy_c2h_dm_func {
|
||||
RTW89_PHY_C2H_DM_FUNC_SIGB,
|
||||
RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY,
|
||||
RTW89_PHY_C2H_DM_FUNC_MCC_DIG,
|
||||
RTW89_PHY_C2H_DM_FUNC_FW_SCAN = 0xc,
|
||||
RTW89_PHY_C2H_DM_FUNC_NUM,
|
||||
};
|
||||
|
||||
@@ -935,6 +936,20 @@ static inline s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm)
|
||||
return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63);
|
||||
}
|
||||
|
||||
static inline s16 rtw89_phy_txpwr_mac_to_rf(struct rtw89_dev *rtwdev, s8 txpwr_mac)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
return txpwr_mac << (chip->txpwr_factor_rf - chip->txpwr_factor_mac);
|
||||
}
|
||||
|
||||
static inline s16 rtw89_phy_txpwr_mac_to_bb(struct rtw89_dev *rtwdev, s8 txpwr_mac)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
return txpwr_mac << (chip->txpwr_factor_bb - chip->txpwr_factor_mac);
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -362,7 +362,7 @@ static void rtw89_phy_bb_wrap_force_cr_init(struct rtw89_dev *rtwdev,
|
||||
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RU_ENON, 0);
|
||||
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_RU_ON, 0);
|
||||
addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_FORCE_MACID, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_MACID_ON, 0);
|
||||
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_MACID_ALL, 0);
|
||||
addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_COEX_CTRL, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, addr, B_BE_PWR_FORCE_COEX_ON, 0);
|
||||
addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_RATE_CTRL, mac_idx);
|
||||
|
||||
@@ -382,3 +382,150 @@ u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data)
|
||||
tail = ie->noa_desc + setter->noa_count;
|
||||
return tail - *data;
|
||||
}
|
||||
|
||||
static void rtw89_ps_noa_once_set_work(struct wiphy *wiphy, struct wiphy_work *work)
|
||||
{
|
||||
struct rtw89_ps_noa_once_handler *noa_once =
|
||||
container_of(work, struct rtw89_ps_noa_once_handler, set_work.work);
|
||||
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
noa_once->in_duration = true;
|
||||
}
|
||||
|
||||
static void rtw89_ps_noa_once_clr_work(struct wiphy *wiphy, struct wiphy_work *work)
|
||||
{
|
||||
struct rtw89_ps_noa_once_handler *noa_once =
|
||||
container_of(work, struct rtw89_ps_noa_once_handler, clr_work.work);
|
||||
struct rtw89_vif_link *rtwvif_link =
|
||||
container_of(noa_once, struct rtw89_vif_link, noa_once);
|
||||
struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
|
||||
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
|
||||
noa_once->in_duration = false;
|
||||
}
|
||||
|
||||
void rtw89_p2p_noa_once_init(struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
|
||||
|
||||
noa_once->in_duration = false;
|
||||
noa_once->tsf_begin = 0;
|
||||
noa_once->tsf_end = 0;
|
||||
|
||||
wiphy_delayed_work_init(&noa_once->set_work, rtw89_ps_noa_once_set_work);
|
||||
wiphy_delayed_work_init(&noa_once->clr_work, rtw89_ps_noa_once_clr_work);
|
||||
}
|
||||
|
||||
static void rtw89_p2p_noa_once_cancel(struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
|
||||
struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
|
||||
struct wiphy *wiphy = rtwdev->hw->wiphy;
|
||||
|
||||
wiphy_delayed_work_cancel(wiphy, &noa_once->set_work);
|
||||
wiphy_delayed_work_cancel(wiphy, &noa_once->clr_work);
|
||||
}
|
||||
|
||||
void rtw89_p2p_noa_once_deinit(struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
rtw89_p2p_noa_once_cancel(rtwvif_link);
|
||||
rtw89_p2p_noa_once_init(rtwvif_link);
|
||||
}
|
||||
|
||||
void rtw89_p2p_noa_once_recalc(struct rtw89_vif_link *rtwvif_link)
|
||||
{
|
||||
struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
|
||||
struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
|
||||
const struct ieee80211_p2p_noa_desc *noa_desc;
|
||||
struct wiphy *wiphy = rtwdev->hw->wiphy;
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
u64 tsf_begin = U64_MAX, tsf_end;
|
||||
u64 set_delay_us = 0;
|
||||
u64 clr_delay_us = 0;
|
||||
u32 start_time;
|
||||
u32 interval;
|
||||
u32 duration;
|
||||
u64 tsf;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
|
||||
if (ret) {
|
||||
rtw89_warn(rtwdev, "%s: failed to get tsf\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bss_conf->p2p_noa_attr.desc); i++) {
|
||||
bool first = tsf_begin == U64_MAX;
|
||||
u64 tmp;
|
||||
|
||||
noa_desc = &bss_conf->p2p_noa_attr.desc[i];
|
||||
if (noa_desc->count == 0 || noa_desc->count == 255)
|
||||
continue;
|
||||
|
||||
start_time = le32_to_cpu(noa_desc->start_time);
|
||||
interval = le32_to_cpu(noa_desc->interval);
|
||||
duration = le32_to_cpu(noa_desc->duration);
|
||||
|
||||
if (unlikely(duration == 0 ||
|
||||
(noa_desc->count > 1 && interval == 0)))
|
||||
continue;
|
||||
|
||||
tmp = start_time + interval * (noa_desc->count - 1) + duration;
|
||||
tmp = (tsf & GENMASK_ULL(63, 32)) + tmp;
|
||||
if (unlikely(tmp <= tsf))
|
||||
continue;
|
||||
tsf_end = first ? tmp : max(tsf_end, tmp);
|
||||
|
||||
tmp = (tsf & GENMASK_ULL(63, 32)) | start_time;
|
||||
tsf_begin = first ? tmp : min(tsf_begin, tmp);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (tsf_begin == U64_MAX)
|
||||
return;
|
||||
|
||||
rtw89_p2p_noa_once_cancel(rtwvif_link);
|
||||
|
||||
if (noa_once->tsf_end > tsf) {
|
||||
tsf_begin = min(tsf_begin, noa_once->tsf_begin);
|
||||
tsf_end = max(tsf_end, noa_once->tsf_end);
|
||||
}
|
||||
|
||||
clr_delay_us = min_t(u64, tsf_end - tsf, UINT_MAX);
|
||||
|
||||
if (tsf_begin <= tsf) {
|
||||
noa_once->in_duration = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_delay_us = tsf_begin - tsf;
|
||||
if (unlikely(set_delay_us > UINT_MAX)) {
|
||||
rtw89_warn(rtwdev, "%s: unhandled begin\n", __func__);
|
||||
set_delay_us = 0;
|
||||
clr_delay_us = 0;
|
||||
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
|
||||
noa_once->in_duration = false;
|
||||
}
|
||||
|
||||
out:
|
||||
if (set_delay_us)
|
||||
wiphy_delayed_work_queue(wiphy, &noa_once->set_work,
|
||||
usecs_to_jiffies(set_delay_us));
|
||||
if (clr_delay_us)
|
||||
wiphy_delayed_work_queue(wiphy, &noa_once->clr_work,
|
||||
usecs_to_jiffies(clr_delay_us));
|
||||
|
||||
noa_once->tsf_begin = tsf_begin;
|
||||
noa_once->tsf_end = tsf_end;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link);
|
||||
void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link,
|
||||
const struct ieee80211_p2p_noa_desc *desc);
|
||||
u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data);
|
||||
void rtw89_p2p_noa_once_init(struct rtw89_vif_link *rtwvif_link);
|
||||
void rtw89_p2p_noa_once_deinit(struct rtw89_vif_link *rtwvif_link);
|
||||
void rtw89_p2p_noa_once_recalc(struct rtw89_vif_link *rtwvif_link);
|
||||
|
||||
static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
|
||||
@@ -7601,7 +7601,15 @@
|
||||
#define B_BE_PWR_FORCE_RU_ON BIT(18)
|
||||
#define B_BE_PWR_FORCE_RU_ENON BIT(28)
|
||||
#define R_BE_PWR_FORCE_MACID 0x11A48
|
||||
#define B_BE_PWR_FORCE_MACID_ON BIT(9)
|
||||
#define B_BE_PWR_FORCE_MACID_DBM_ON BIT(9)
|
||||
#define B_BE_PWR_FORCE_MACID_DBM_VAL GENMASK(17, 10)
|
||||
#define B_BE_PWR_FORCE_MACID_EN_VAL BIT(18)
|
||||
#define B_BE_PWR_FORCE_MACID_EN_ON BIT(19)
|
||||
#define B_BE_PWR_FORCE_MACID_ALL \
|
||||
(B_BE_PWR_FORCE_MACID_DBM_ON | \
|
||||
B_BE_PWR_FORCE_MACID_DBM_VAL | \
|
||||
B_BE_PWR_FORCE_MACID_EN_VAL | \
|
||||
B_BE_PWR_FORCE_MACID_EN_ON)
|
||||
|
||||
#define R_BE_PWR_REG_CTRL 0x11A50
|
||||
#define B_BE_PWR_BT_EN BIT(23)
|
||||
@@ -8737,8 +8745,10 @@
|
||||
#define B_DPD_GDIS BIT(13)
|
||||
#define B_IQK_RFC_ON BIT(1)
|
||||
#define R_TXPWRB 0x56CC
|
||||
#define R_P1_TXPWRB 0x76CC
|
||||
#define B_TXPWRB_ON BIT(28)
|
||||
#define B_TXPWRB_VAL GENMASK(27, 19)
|
||||
#define B_TXPWRB_MAX GENMASK(8, 0)
|
||||
#define R_DPD_OFT_EN 0x5800
|
||||
#define B_DPD_OFT_EN BIT(28)
|
||||
#define B_DPD_TSSI_CW GENMASK(26, 18)
|
||||
@@ -9360,6 +9370,9 @@
|
||||
#define R_TSSI_PWR_P0 0xE610
|
||||
#define R_TSSI_PWR_P1 0xE710
|
||||
#define B_TSSI_CONT_EN BIT(3)
|
||||
#define R_P0_TXPWRB_BE 0xE61C
|
||||
#define R_P1_TXPWRB_BE 0xE71C
|
||||
#define B_TXPWRB_MAX_BE GENMASK(20, 12)
|
||||
#define R_TSSI_MAP_OFST_P0 0xE620
|
||||
#define R_TSSI_MAP_OFST_P1 0xE720
|
||||
#define B_TSSI_MAP_OFST_OFDM GENMASK(17, 9)
|
||||
|
||||
@@ -588,6 +588,38 @@ static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
|
||||
kfree(sband);
|
||||
}
|
||||
|
||||
#define RTW89_DEF_REGD_STR(regd) \
|
||||
[RTW89_ ## regd] = #regd
|
||||
|
||||
static const char * const rtw89_regd_string[] = {
|
||||
RTW89_DEF_REGD_STR(WW),
|
||||
RTW89_DEF_REGD_STR(ETSI),
|
||||
RTW89_DEF_REGD_STR(FCC),
|
||||
RTW89_DEF_REGD_STR(MKK),
|
||||
RTW89_DEF_REGD_STR(NA),
|
||||
RTW89_DEF_REGD_STR(IC),
|
||||
RTW89_DEF_REGD_STR(KCC),
|
||||
RTW89_DEF_REGD_STR(ACMA),
|
||||
RTW89_DEF_REGD_STR(NCC),
|
||||
RTW89_DEF_REGD_STR(MEXICO),
|
||||
RTW89_DEF_REGD_STR(CHILE),
|
||||
RTW89_DEF_REGD_STR(UKRAINE),
|
||||
RTW89_DEF_REGD_STR(CN),
|
||||
RTW89_DEF_REGD_STR(QATAR),
|
||||
RTW89_DEF_REGD_STR(UK),
|
||||
RTW89_DEF_REGD_STR(THAILAND),
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(rtw89_regd_string) == RTW89_REGD_NUM);
|
||||
|
||||
const char *rtw89_regd_get_string(enum rtw89_regulation_type regd)
|
||||
{
|
||||
if (regd < 0 || regd >= RTW89_REGD_NUM)
|
||||
return "(unknown)";
|
||||
|
||||
return rtw89_regd_string[regd];
|
||||
}
|
||||
|
||||
int rtw89_regd_setup(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
@@ -604,6 +636,7 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
|
||||
regulatory->txpwr_uk_follow_etsi = true;
|
||||
|
||||
if (!wiphy)
|
||||
return -EINVAL;
|
||||
@@ -726,11 +759,22 @@ static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
const struct rtw89_regd *regd = regulatory->regd;
|
||||
struct rtw89_tas_info *tas = &rtwdev->tas;
|
||||
u8 tas_country;
|
||||
|
||||
if (!tas->enable)
|
||||
return;
|
||||
|
||||
tas->block_regd = !test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap);
|
||||
if (memcmp("US", regd->alpha2, 2) == 0)
|
||||
tas_country = RTW89_ACPI_CONF_TAS_US;
|
||||
else if (memcmp("CA", regd->alpha2, 2) == 0)
|
||||
tas_country = RTW89_ACPI_CONF_TAS_CA;
|
||||
else if (memcmp("KR", regd->alpha2, 2) == 0)
|
||||
tas_country = RTW89_ACPI_CONF_TAS_KR;
|
||||
else
|
||||
tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
|
||||
|
||||
tas->block_regd = !(tas->enabled_countries & tas_country &&
|
||||
test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
|
||||
}
|
||||
|
||||
static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
|
||||
|
||||
@@ -2499,12 +2499,14 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
|
||||
.support_unii4 = true,
|
||||
.support_ant_gain = false,
|
||||
.support_tas = false,
|
||||
.support_sar_by_ant = false,
|
||||
.ul_tb_waveform_ctrl = true,
|
||||
.ul_tb_pwr_diff = false,
|
||||
.rx_freq_frome_ie = true,
|
||||
.hw_sec_hdr = false,
|
||||
.hw_mgmt_tx_encrypt = false,
|
||||
.hw_tkip_crypto = false,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 1,
|
||||
.tx_nss = 1,
|
||||
.rx_nss = 1,
|
||||
|
||||
@@ -2217,12 +2217,14 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||
.support_unii4 = false,
|
||||
.support_ant_gain = false,
|
||||
.support_tas = false,
|
||||
.support_sar_by_ant = false,
|
||||
.ul_tb_waveform_ctrl = false,
|
||||
.ul_tb_pwr_diff = false,
|
||||
.rx_freq_frome_ie = true,
|
||||
.hw_sec_hdr = false,
|
||||
.hw_mgmt_tx_encrypt = false,
|
||||
.hw_tkip_crypto = false,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 2,
|
||||
.tx_nss = 2,
|
||||
.rx_nss = 2,
|
||||
|
||||
@@ -853,12 +853,14 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
|
||||
.support_unii4 = true,
|
||||
.support_ant_gain = true,
|
||||
.support_tas = false,
|
||||
.support_sar_by_ant = true,
|
||||
.ul_tb_waveform_ctrl = true,
|
||||
.ul_tb_pwr_diff = false,
|
||||
.rx_freq_frome_ie = true,
|
||||
.hw_sec_hdr = false,
|
||||
.hw_mgmt_tx_encrypt = false,
|
||||
.hw_tkip_crypto = false,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 2,
|
||||
.tx_nss = 2,
|
||||
.rx_nss = 2,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "phy.h"
|
||||
#include "reg.h"
|
||||
#include "rtw8852b_common.h"
|
||||
#include "sar.h"
|
||||
#include "util.h"
|
||||
|
||||
static const struct rtw89_reg3_def rtw8852bx_pmac_ht20_mcs7_tbl[] = {
|
||||
@@ -1234,6 +1235,7 @@ static u32 rtw8852bx_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
|
||||
u32_encode_bits(ref, B_DPD_REF);
|
||||
}
|
||||
|
||||
/* @pwr_ofst (unit: 1/8 dBm): power of path A minus power of path B */
|
||||
static void rtw8852bx_set_txpwr_ref(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx, s16 pwr_ofst)
|
||||
{
|
||||
@@ -1336,6 +1338,27 @@ static void rtw8852bx_set_tx_shape(struct rtw89_dev *rtwdev,
|
||||
tx_shape_ofdm);
|
||||
}
|
||||
|
||||
static s16 rtw8852bx_get_txpwr_sar_diff(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan)
|
||||
{
|
||||
struct rtw89_sar_parm sar_parm = {
|
||||
.center_freq = chan->freq,
|
||||
.force_path = true,
|
||||
};
|
||||
s16 sar_bb_a, sar_bb_b;
|
||||
s8 sar_mac;
|
||||
|
||||
sar_parm.path = RF_PATH_A;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_bb_a = rtw89_phy_txpwr_mac_to_bb(rtwdev, sar_mac);
|
||||
|
||||
sar_parm.path = RF_PATH_B;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_bb_b = rtw89_phy_txpwr_mac_to_bb(rtwdev, sar_mac);
|
||||
|
||||
return sar_bb_a - sar_bb_b;
|
||||
}
|
||||
|
||||
static void rtw8852bx_set_txpwr_diff(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
@@ -1343,6 +1366,7 @@ static void rtw8852bx_set_txpwr_diff(struct rtw89_dev *rtwdev,
|
||||
s16 pwr_ofst;
|
||||
|
||||
pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan);
|
||||
pwr_ofst += rtw8852bx_get_txpwr_sar_diff(rtwdev, chan);
|
||||
rtw8852bx_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst);
|
||||
}
|
||||
|
||||
|
||||
@@ -786,12 +786,14 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
|
||||
.support_unii4 = true,
|
||||
.support_ant_gain = true,
|
||||
.support_tas = false,
|
||||
.support_sar_by_ant = true,
|
||||
.ul_tb_waveform_ctrl = true,
|
||||
.ul_tb_pwr_diff = false,
|
||||
.rx_freq_frome_ie = true,
|
||||
.hw_sec_hdr = false,
|
||||
.hw_mgmt_tx_encrypt = false,
|
||||
.hw_tkip_crypto = true,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 2,
|
||||
.tx_nss = 2,
|
||||
.rx_nss = 2,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "sar.h"
|
||||
#include "util.h"
|
||||
|
||||
#define RTW8852C_FW_FORMAT_MAX 1
|
||||
#define RTW8852C_FW_FORMAT_MAX 2
|
||||
#define RTW8852C_FW_BASENAME "rtw89/rtw8852c_fw"
|
||||
#define RTW8852C_MODULE_FIRMWARE \
|
||||
RTW8852C_FW_BASENAME "-" __stringify(RTW8852C_FW_FORMAT_MAX) ".bin"
|
||||
@@ -2079,6 +2079,31 @@ static void rtw8852c_set_txpwr_diff(struct rtw89_dev *rtwdev,
|
||||
rtw8852c_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst);
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_sar_diff(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
struct rtw89_sar_parm sar_parm = {
|
||||
.center_freq = chan->freq,
|
||||
.force_path = true,
|
||||
};
|
||||
s16 sar_rf;
|
||||
s8 sar_mac;
|
||||
|
||||
if (phy_idx != RTW89_PHY_0)
|
||||
return;
|
||||
|
||||
sar_parm.path = RF_PATH_A;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac);
|
||||
rtw89_phy_write32_mask(rtwdev, R_TXPWRB, B_TXPWRB_MAX, sar_rf);
|
||||
|
||||
sar_parm.path = RF_PATH_B;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac);
|
||||
rtw89_phy_write32_mask(rtwdev, R_P1_TXPWRB, B_TXPWRB_MAX, sar_rf);
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
@@ -2089,6 +2114,7 @@ static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
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);
|
||||
rtw8852c_set_txpwr_sar_diff(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
|
||||
@@ -3014,12 +3040,14 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
.support_unii4 = true,
|
||||
.support_ant_gain = true,
|
||||
.support_tas = true,
|
||||
.support_sar_by_ant = true,
|
||||
.ul_tb_waveform_ctrl = false,
|
||||
.ul_tb_pwr_diff = true,
|
||||
.rx_freq_frome_ie = false,
|
||||
.hw_sec_hdr = true,
|
||||
.hw_mgmt_tx_encrypt = true,
|
||||
.hw_tkip_crypto = true,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 2,
|
||||
.tx_nss = 2,
|
||||
.rx_nss = 2,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "reg.h"
|
||||
#include "rtw8922a.h"
|
||||
#include "rtw8922a_rfk.h"
|
||||
#include "sar.h"
|
||||
#include "util.h"
|
||||
|
||||
#define RTW8922A_FW_FORMAT_MAX 3
|
||||
@@ -2070,7 +2071,8 @@ static void __rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev,
|
||||
rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5);
|
||||
|
||||
rtw89_phy_rfk_dack_and_wait(rtwdev, phy_idx, chan, 58);
|
||||
rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 32);
|
||||
if (!test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
|
||||
rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 128);
|
||||
}
|
||||
|
||||
static void rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev)
|
||||
@@ -2233,6 +2235,31 @@ static void rtw8922a_set_tx_shape(struct rtw89_dev *rtwdev,
|
||||
rtw8922a_bb_tx_triangular(rtwdev, true, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8922a_set_txpwr_sar_diff(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
struct rtw89_sar_parm sar_parm = {
|
||||
.center_freq = chan->freq,
|
||||
.force_path = true,
|
||||
};
|
||||
s16 sar_rf;
|
||||
s8 sar_mac;
|
||||
|
||||
if (phy_idx != RTW89_PHY_0)
|
||||
return;
|
||||
|
||||
sar_parm.path = RF_PATH_A;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac);
|
||||
rtw89_phy_write32_mask(rtwdev, R_P0_TXPWRB_BE, B_TXPWRB_MAX_BE, sar_rf);
|
||||
|
||||
sar_parm.path = RF_PATH_B;
|
||||
sar_mac = rtw89_query_sar(rtwdev, &sar_parm);
|
||||
sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac);
|
||||
rtw89_phy_write32_mask(rtwdev, R_P1_TXPWRB_BE, B_TXPWRB_MAX_BE, sar_rf);
|
||||
}
|
||||
|
||||
static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
@@ -2244,6 +2271,7 @@ static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
|
||||
rtw8922a_set_txpwr_diff(rtwdev, chan, phy_idx);
|
||||
rtw8922a_set_txpwr_ref(rtwdev, phy_idx);
|
||||
rtw8922a_set_txpwr_sar_diff(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8922a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
|
||||
@@ -2823,12 +2851,14 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
|
||||
.support_unii4 = true,
|
||||
.support_ant_gain = true,
|
||||
.support_tas = false,
|
||||
.support_sar_by_ant = true,
|
||||
.ul_tb_waveform_ctrl = false,
|
||||
.ul_tb_pwr_diff = false,
|
||||
.rx_freq_frome_ie = false,
|
||||
.hw_sec_hdr = true,
|
||||
.hw_mgmt_tx_encrypt = true,
|
||||
.hw_tkip_crypto = true,
|
||||
.hw_mlo_bmc_crypto = false,
|
||||
.rf_path_num = 2,
|
||||
.tx_nss = 2,
|
||||
.rx_nss = 2,
|
||||
|
||||
@@ -77,11 +77,6 @@ void rtw8922a_ctl_band_ch_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
RR_CFGCH_BAND0 | RR_CFGCH_CH);
|
||||
rf_reg[path][i] |= u32_encode_bits(central_ch, RR_CFGCH_CH);
|
||||
|
||||
if (band == RTW89_BAND_2G)
|
||||
rtw89_write_rf(rtwdev, path, RR_SMD, RR_VCO2, 0x0);
|
||||
else
|
||||
rtw89_write_rf(rtwdev, path, RR_SMD, RR_VCO2, 0x1);
|
||||
|
||||
switch (band) {
|
||||
case RTW89_BAND_2G:
|
||||
default:
|
||||
|
||||
@@ -57,10 +57,12 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
|
||||
u32 center_freq, s32 *cfg)
|
||||
const struct rtw89_sar_parm *sar_parm,
|
||||
s32 *cfg)
|
||||
{
|
||||
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
|
||||
enum rtw89_sar_subband subband_l, subband_h;
|
||||
u32 center_freq = sar_parm->center_freq;
|
||||
const struct rtw89_6ghz_span *span;
|
||||
|
||||
span = rtw89_get_6ghz_span(rtwdev, center_freq);
|
||||
@@ -90,6 +92,93 @@ static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rtw89_sar_entry_from_acpi *
|
||||
rtw89_sar_cfg_acpi_get_ent(const struct rtw89_sar_cfg_acpi *rtwsar,
|
||||
enum rtw89_rf_path path,
|
||||
enum rtw89_regulation_type regd)
|
||||
{
|
||||
const struct rtw89_sar_indicator_from_acpi *ind = &rtwsar->indicator;
|
||||
const struct rtw89_sar_table_from_acpi *tbl;
|
||||
u8 sel;
|
||||
|
||||
sel = ind->tblsel[path];
|
||||
tbl = &rtwsar->tables[sel];
|
||||
|
||||
return &tbl->entries[regd];
|
||||
}
|
||||
|
||||
static
|
||||
s32 rtw89_sar_cfg_acpi_get_min(const struct rtw89_sar_entry_from_acpi *ent,
|
||||
enum rtw89_rf_path path,
|
||||
enum rtw89_acpi_sar_subband subband_low,
|
||||
enum rtw89_acpi_sar_subband subband_high)
|
||||
{
|
||||
return min(ent->v[subband_low][path], ent->v[subband_high][path]);
|
||||
}
|
||||
|
||||
static int rtw89_query_sar_config_acpi(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_sar_parm *sar_parm,
|
||||
s32 *cfg)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw89_sar_cfg_acpi *rtwsar = &rtwdev->sar.cfg_acpi;
|
||||
const struct rtw89_sar_entry_from_acpi *ent_a, *ent_b;
|
||||
enum rtw89_acpi_sar_subband subband_l, subband_h;
|
||||
u32 center_freq = sar_parm->center_freq;
|
||||
const struct rtw89_6ghz_span *span;
|
||||
enum rtw89_regulation_type regd;
|
||||
enum rtw89_band band;
|
||||
s32 cfg_a, cfg_b;
|
||||
|
||||
span = rtw89_get_6ghz_span(rtwdev, center_freq);
|
||||
|
||||
if (span && RTW89_ACPI_SAR_SPAN_VALID(span)) {
|
||||
subband_l = span->acpi_sar_subband_low;
|
||||
subband_h = span->acpi_sar_subband_high;
|
||||
} else {
|
||||
subband_l = rtw89_acpi_sar_get_subband(rtwdev, center_freq);
|
||||
subband_h = subband_l;
|
||||
}
|
||||
|
||||
band = rtw89_acpi_sar_subband_to_band(rtwdev, subband_l);
|
||||
regd = rtw89_regd_get(rtwdev, band);
|
||||
|
||||
ent_a = rtw89_sar_cfg_acpi_get_ent(rtwsar, RF_PATH_A, regd);
|
||||
ent_b = rtw89_sar_cfg_acpi_get_ent(rtwsar, RF_PATH_B, regd);
|
||||
|
||||
cfg_a = rtw89_sar_cfg_acpi_get_min(ent_a, RF_PATH_A, subband_l, subband_h);
|
||||
cfg_b = rtw89_sar_cfg_acpi_get_min(ent_b, RF_PATH_B, subband_l, subband_h);
|
||||
|
||||
if (chip->support_sar_by_ant) {
|
||||
/* With declaration of support_sar_by_ant, relax the general
|
||||
* SAR querying to return the maximum between paths. However,
|
||||
* expect chip has dealt with the corresponding SAR settings
|
||||
* by path. (To get SAR for a given path, chip can then query
|
||||
* with force_path.)
|
||||
*/
|
||||
if (sar_parm->force_path) {
|
||||
switch (sar_parm->path) {
|
||||
default:
|
||||
case RF_PATH_A:
|
||||
*cfg = cfg_a;
|
||||
break;
|
||||
case RF_PATH_B:
|
||||
*cfg = cfg_b;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*cfg = max(cfg_a, cfg_b);
|
||||
}
|
||||
} else {
|
||||
*cfg = min(cfg_a, cfg_b);
|
||||
}
|
||||
|
||||
if (sar_parm->ntx == RTW89_2TX)
|
||||
*cfg -= rtwsar->downgrade_2tx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const
|
||||
struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = {
|
||||
[RTW89_SAR_SOURCE_COMMON] = {
|
||||
@@ -97,6 +186,11 @@ struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = {
|
||||
.txpwr_factor_sar = 2,
|
||||
.query_sar_config = rtw89_query_sar_config_common,
|
||||
},
|
||||
[RTW89_SAR_SOURCE_ACPI] = {
|
||||
.descr_sar_source = "RTW89_SAR_SOURCE_ACPI",
|
||||
.txpwr_factor_sar = TXPWR_FACTOR_OF_RTW89_ACPI_SAR,
|
||||
.query_sar_config = rtw89_query_sar_config_acpi,
|
||||
},
|
||||
};
|
||||
|
||||
#define rtw89_sar_set_src(_dev, _src, _cfg_name, _cfg_data) \
|
||||
@@ -175,7 +269,7 @@ static const char *rtw89_tas_state_str(enum rtw89_tas_state state)
|
||||
}
|
||||
}
|
||||
|
||||
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
|
||||
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, const struct rtw89_sar_parm *sar_parm)
|
||||
{
|
||||
const enum rtw89_sar_sources src = rtwdev->sar.src;
|
||||
/* its members are protected by rtw89_sar_set_src() */
|
||||
@@ -191,7 +285,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
|
||||
if (src == RTW89_SAR_SOURCE_NONE)
|
||||
return RTW89_SAR_TXPWR_MAC_MAX;
|
||||
|
||||
ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
|
||||
ret = sar_hdl->query_sar_config(rtwdev, sar_parm, &cfg);
|
||||
if (ret)
|
||||
return RTW89_SAR_TXPWR_MAC_MAX;
|
||||
|
||||
@@ -215,9 +309,10 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
|
||||
|
||||
return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_query_sar);
|
||||
|
||||
int rtw89_print_sar(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
u32 center_freq)
|
||||
const struct rtw89_sar_parm *sar_parm)
|
||||
{
|
||||
const enum rtw89_sar_sources src = rtwdev->sar.src;
|
||||
/* its members are protected by rtw89_sar_set_src() */
|
||||
@@ -238,7 +333,7 @@ int rtw89_print_sar(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
p += scnprintf(p, end - p, "source: %d (%s)\n", src,
|
||||
sar_hdl->descr_sar_source);
|
||||
|
||||
ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
|
||||
ret = sar_hdl->query_sar_config(rtwdev, sar_parm, &cfg);
|
||||
if (ret) {
|
||||
p += scnprintf(p, end - p, "config: return code: %d\n", ret);
|
||||
p += scnprintf(p, end - p,
|
||||
@@ -252,6 +347,8 @@ int rtw89_print_sar(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
p += scnprintf(p, end - p, "config: %d (unit: 1/%lu dBm)\n", cfg,
|
||||
BIT(fct));
|
||||
|
||||
p += scnprintf(p, end - p, "support different configs by antenna: %s\n",
|
||||
str_yes_no(rtwdev->chip->support_sar_by_ant));
|
||||
out:
|
||||
return p - buf;
|
||||
}
|
||||
@@ -286,16 +383,7 @@ int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
|
||||
static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_sar_cfg_common *sar)
|
||||
{
|
||||
enum rtw89_sar_sources src;
|
||||
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
src = rtwdev->sar.src;
|
||||
if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON) {
|
||||
rtw89_warn(rtwdev, "SAR source: %d is in use", src);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* let common SAR have the highest priority; always apply it */
|
||||
rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
rtw89_tas_reset(rtwdev, false);
|
||||
@@ -363,18 +451,92 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
|
||||
return rtw89_apply_sar_common(rtwdev, &sar_common);
|
||||
}
|
||||
|
||||
static void rtw89_apply_sar_acpi(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_sar_cfg_acpi *sar)
|
||||
{
|
||||
const struct rtw89_sar_table_from_acpi *tbl;
|
||||
const struct rtw89_sar_entry_from_acpi *ent;
|
||||
enum rtw89_sar_sources src;
|
||||
unsigned int i, j, k;
|
||||
|
||||
src = rtwdev->sar.src;
|
||||
if (src != RTW89_SAR_SOURCE_NONE) {
|
||||
rtw89_warn(rtwdev, "SAR source: %d is in use", src);
|
||||
return;
|
||||
}
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR,
|
||||
"SAR-ACPI downgrade 2TX: %u (unit: 1/%lu dBm)\n",
|
||||
sar->downgrade_2tx, BIT(TXPWR_FACTOR_OF_RTW89_ACPI_SAR));
|
||||
|
||||
for (i = 0; i < sar->valid_num; i++) {
|
||||
tbl = &sar->tables[i];
|
||||
|
||||
for (j = 0; j < RTW89_REGD_NUM; j++) {
|
||||
ent = &tbl->entries[j];
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR,
|
||||
"SAR-ACPI-[%u] REGD-%s (unit: 1/%lu dBm)\n",
|
||||
i, rtw89_regd_get_string(j),
|
||||
BIT(TXPWR_FACTOR_OF_RTW89_ACPI_SAR));
|
||||
|
||||
for (k = 0; k < NUM_OF_RTW89_ACPI_SAR_SUBBAND; k++)
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR,
|
||||
"On subband %u, { %d, %d }\n", k,
|
||||
ent->v[k][RF_PATH_A], ent->v[k][RF_PATH_B]);
|
||||
}
|
||||
}
|
||||
|
||||
rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_ACPI, cfg_acpi, sar);
|
||||
|
||||
/* SAR via ACPI is only configured in the early initial phase, so
|
||||
* it does not seem necessary to reset txpwr related things here.
|
||||
*/
|
||||
}
|
||||
|
||||
static void rtw89_set_sar_from_acpi(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_sar_cfg_acpi *cfg;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
ret = rtw89_acpi_evaluate_sar(rtwdev, cfg);
|
||||
if (ret) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR,
|
||||
"evaluating ACPI SAR returns %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(!cfg->valid_num)) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR, "no valid SAR table from ACPI\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rtw89_apply_sar_acpi(rtwdev, cfg);
|
||||
|
||||
out:
|
||||
kfree(cfg);
|
||||
}
|
||||
|
||||
static bool rtw89_tas_query_sar_config(struct rtw89_dev *rtwdev, s32 *cfg)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
|
||||
const enum rtw89_sar_sources src = rtwdev->sar.src;
|
||||
/* its members are protected by rtw89_sar_set_src() */
|
||||
const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
|
||||
struct rtw89_sar_parm sar_parm = {};
|
||||
int ret;
|
||||
|
||||
if (src == RTW89_SAR_SOURCE_NONE)
|
||||
return false;
|
||||
|
||||
ret = sar_hdl->query_sar_config(rtwdev, chan->freq, cfg);
|
||||
sar_parm.center_freq = chan->freq;
|
||||
ret = sar_hdl->query_sar_config(rtwdev, &sar_parm, cfg);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
@@ -383,18 +545,27 @@ static bool rtw89_tas_query_sar_config(struct rtw89_dev *rtwdev, s32 *cfg)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rtw89_tas_state_update(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_tas_state state)
|
||||
static bool __rtw89_tas_state_update(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_tas_state state)
|
||||
{
|
||||
struct rtw89_tas_info *tas = &rtwdev->tas;
|
||||
|
||||
if (tas->state == state)
|
||||
return;
|
||||
return false;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR, "tas: switch state: %s -> %s\n",
|
||||
rtw89_tas_state_str(tas->state), rtw89_tas_state_str(state));
|
||||
|
||||
tas->state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rtw89_tas_state_update(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_tas_state state)
|
||||
{
|
||||
if (!__rtw89_tas_state_update(rtwdev, state))
|
||||
return;
|
||||
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
}
|
||||
|
||||
@@ -489,7 +660,7 @@ static void rtw89_tas_history_update(struct rtw89_dev *rtwdev)
|
||||
rtw89_linear_to_db_quarter(div_u64(txpwr, PERCENT)));
|
||||
}
|
||||
|
||||
static void rtw89_tas_rolling_average(struct rtw89_dev *rtwdev)
|
||||
static bool rtw89_tas_rolling_average(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_tas_info *tas = &rtwdev->tas;
|
||||
s32 dpr_on_threshold, dpr_off_threshold;
|
||||
@@ -515,18 +686,18 @@ static void rtw89_tas_rolling_average(struct rtw89_dev *rtwdev)
|
||||
else if (txpwr_avg < dpr_off_threshold)
|
||||
state = RTW89_TAS_STATE_DPR_OFF;
|
||||
else
|
||||
return;
|
||||
return false;
|
||||
|
||||
rtw89_tas_state_update(rtwdev, state);
|
||||
return __rtw89_tas_state_update(rtwdev, state);
|
||||
}
|
||||
|
||||
void rtw89_tas_init(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_tas_init(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_tas_info *tas = &rtwdev->tas;
|
||||
const struct rtw89_acpi_policy_tas *ptr;
|
||||
struct rtw89_acpi_dsm_result res = {};
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (!chip->support_tas)
|
||||
return;
|
||||
@@ -538,8 +709,9 @@ void rtw89_tas_init(struct rtw89_dev *rtwdev)
|
||||
return;
|
||||
}
|
||||
|
||||
val = res.u.value;
|
||||
switch (val) {
|
||||
ptr = res.u.policy_tas;
|
||||
|
||||
switch (ptr->enable) {
|
||||
case 0:
|
||||
tas->enable = false;
|
||||
break;
|
||||
@@ -552,8 +724,13 @@ void rtw89_tas_init(struct rtw89_dev *rtwdev)
|
||||
|
||||
if (!tas->enable) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tas->enabled_countries = ptr->enabled_countries;
|
||||
|
||||
out:
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force)
|
||||
@@ -598,29 +775,28 @@ void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force)
|
||||
"tas: band: %u, freq: %u\n", chan->band_type, chan->freq);
|
||||
}
|
||||
|
||||
void rtw89_tas_track(struct rtw89_dev *rtwdev)
|
||||
static bool rtw89_tas_track(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_tas_info *tas = &rtwdev->tas;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
s32 cfg;
|
||||
|
||||
if (hal->disabled_dm_bitmap & BIT(RTW89_DM_TAS))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (!rtw89_tas_is_active(rtwdev))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (!rtw89_tas_query_sar_config(rtwdev, &cfg) || tas->block_regd) {
|
||||
rtw89_tas_state_update(rtwdev, RTW89_TAS_STATE_STATIC_SAR);
|
||||
return;
|
||||
}
|
||||
if (!rtw89_tas_query_sar_config(rtwdev, &cfg) || tas->block_regd)
|
||||
return __rtw89_tas_state_update(rtwdev, RTW89_TAS_STATE_STATIC_SAR);
|
||||
|
||||
if (tas->pause)
|
||||
return;
|
||||
return false;
|
||||
|
||||
rtw89_tas_window_update(rtwdev);
|
||||
rtw89_tas_history_update(rtwdev);
|
||||
rtw89_tas_rolling_average(rtwdev);
|
||||
|
||||
return rtw89_tas_rolling_average(rtwdev);
|
||||
}
|
||||
|
||||
void rtw89_tas_scan(struct rtw89_dev *rtwdev, bool start)
|
||||
@@ -667,3 +843,51 @@ void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_tas_chanctx_cb);
|
||||
|
||||
void rtw89_sar_init(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
rtw89_set_sar_from_acpi(rtwdev);
|
||||
rtw89_tas_init(rtwdev);
|
||||
}
|
||||
|
||||
static bool rtw89_sar_track_acpi(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_sar_cfg_acpi *cfg = &rtwdev->sar.cfg_acpi;
|
||||
struct rtw89_sar_indicator_from_acpi *ind = &cfg->indicator;
|
||||
const enum rtw89_sar_sources src = rtwdev->sar.src;
|
||||
bool changed;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
if (src != RTW89_SAR_SOURCE_ACPI)
|
||||
return false;
|
||||
|
||||
if (!ind->enable_sync)
|
||||
return false;
|
||||
|
||||
ret = rtw89_acpi_evaluate_dynamic_sar_indicator(rtwdev, cfg, &changed);
|
||||
if (likely(!ret))
|
||||
return changed;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SAR,
|
||||
"%s: failed to track indicator: %d; reset and disable\n",
|
||||
__func__, ret);
|
||||
|
||||
memset(ind->tblsel, 0, sizeof(ind->tblsel));
|
||||
ind->enable_sync = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void rtw89_sar_track(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
unsigned int changes = 0;
|
||||
|
||||
changes += rtw89_sar_track_acpi(rtwdev);
|
||||
changes += rtw89_tas_track(rtwdev);
|
||||
|
||||
if (!changes)
|
||||
return;
|
||||
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
}
|
||||
|
||||
@@ -10,25 +10,34 @@
|
||||
#define RTW89_SAR_TXPWR_MAC_MAX 63
|
||||
#define RTW89_SAR_TXPWR_MAC_MIN -64
|
||||
|
||||
struct rtw89_sar_parm {
|
||||
u32 center_freq;
|
||||
enum rtw89_ntx ntx;
|
||||
|
||||
bool force_path;
|
||||
enum rtw89_rf_path path;
|
||||
};
|
||||
|
||||
struct rtw89_sar_handler {
|
||||
const char *descr_sar_source;
|
||||
u8 txpwr_factor_sar;
|
||||
int (*query_sar_config)(struct rtw89_dev *rtwdev, u32 center_freq, s32 *cfg);
|
||||
int (*query_sar_config)(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_sar_parm *sar_parm, s32 *cfg);
|
||||
};
|
||||
|
||||
extern const struct cfg80211_sar_capa rtw89_sar_capa;
|
||||
|
||||
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq);
|
||||
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, const struct rtw89_sar_parm *sar_parm);
|
||||
int rtw89_print_sar(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
|
||||
u32 center_freq);
|
||||
const struct rtw89_sar_parm *sar_parm);
|
||||
int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz);
|
||||
int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar);
|
||||
void rtw89_tas_init(struct rtw89_dev *rtwdev);
|
||||
void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force);
|
||||
void rtw89_tas_track(struct rtw89_dev *rtwdev);
|
||||
void rtw89_tas_scan(struct rtw89_dev *rtwdev, bool start);
|
||||
void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_chanctx_state state);
|
||||
void rtw89_sar_init(struct rtw89_dev *rtwdev);
|
||||
void rtw89_sar_track(struct rtw89_dev *rtwdev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -309,6 +309,9 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port);
|
||||
rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
|
||||
rtwvif_link->trigger = false;
|
||||
rtwvif_link->rand_tsf_done = false;
|
||||
|
||||
rtw89_p2p_noa_once_deinit(rtwvif_link);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -712,6 +712,25 @@ static inline u8 rtw89_core_get_qsel(struct rtw89_dev *rtwdev, u8 tid)
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8
|
||||
rtw89_core_get_qsel_mgmt(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req)
|
||||
{
|
||||
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
|
||||
struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
|
||||
|
||||
if (desc_info->hiq) {
|
||||
if (rtwvif_link->mac_idx == RTW89_MAC_1)
|
||||
return RTW89_TX_QSEL_B1_HI;
|
||||
else
|
||||
return RTW89_TX_QSEL_B0_HI;
|
||||
}
|
||||
|
||||
if (rtwvif_link->mac_idx == RTW89_MAC_1)
|
||||
return RTW89_TX_QSEL_B1_MGMT;
|
||||
else
|
||||
return RTW89_TX_QSEL_B0_MGMT;
|
||||
}
|
||||
|
||||
static inline u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel)
|
||||
{
|
||||
switch (qsel) {
|
||||
@@ -719,12 +738,24 @@ static inline u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel)
|
||||
rtw89_warn(rtwdev, "Cannot map qsel to dma: %d\n", qsel);
|
||||
fallthrough;
|
||||
case RTW89_TX_QSEL_BE_0:
|
||||
case RTW89_TX_QSEL_BE_1:
|
||||
case RTW89_TX_QSEL_BE_2:
|
||||
case RTW89_TX_QSEL_BE_3:
|
||||
return RTW89_TXCH_ACH0;
|
||||
case RTW89_TX_QSEL_BK_0:
|
||||
case RTW89_TX_QSEL_BK_1:
|
||||
case RTW89_TX_QSEL_BK_2:
|
||||
case RTW89_TX_QSEL_BK_3:
|
||||
return RTW89_TXCH_ACH1;
|
||||
case RTW89_TX_QSEL_VI_0:
|
||||
case RTW89_TX_QSEL_VI_1:
|
||||
case RTW89_TX_QSEL_VI_2:
|
||||
case RTW89_TX_QSEL_VI_3:
|
||||
return RTW89_TXCH_ACH2;
|
||||
case RTW89_TX_QSEL_VO_0:
|
||||
case RTW89_TX_QSEL_VO_1:
|
||||
case RTW89_TX_QSEL_VO_2:
|
||||
case RTW89_TX_QSEL_VO_3:
|
||||
return RTW89_TXCH_ACH3;
|
||||
case RTW89_TX_QSEL_B0_MGMT:
|
||||
return RTW89_TXCH_CH8;
|
||||
|
||||
@@ -1086,8 +1086,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
|
||||
rtw89_wow_init_pno(rtwdev, wowlan->nd_config);
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
|
||||
/* use the link on HW-0 to do wow flow */
|
||||
rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
|
||||
rtwvif_link = rtw89_get_designated_link(rtwvif);
|
||||
if (!rtwvif_link)
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user