summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-06-10 18:57:33 +0300
committerJakub Kicinski <kuba@kernel.org>2022-06-10 18:57:35 +0300
commitb97dcb85750b7e8bc5aaed5403ddf4b0552c7993 (patch)
tree88b9264c730054096a9231bb8cf03fc3d5f56750 /drivers/net/wireless/realtek
parent7defbc9aed2b1fdf21586b78e085c468fd95a2d1 (diff)
parent1449c24e71a343a033af8de0842d1edb8a37926a (diff)
downloadlinux-b97dcb85750b7e8bc5aaed5403ddf4b0552c7993.tar.xz
Merge tag 'wireless-next-2022-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Johannes Berg says: ==================== wireless-next patches for v5.20 Here's a first set of patches for v5.20. This is just a queue flush, before we get things back from net-next that are causing conflicts, and then can start merging a lot of MLO (multi-link operation, part of 802.11be) code. Lots of cleanups all over. The only notable change is perhaps wilc1000 being the first driver to disable WEP (while enabling WPA3). * tag 'wireless-next-2022-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (29 commits) wifi: mac80211_hwsim: Directly use ida_alloc()/free() wifi: mac80211: refactor some key code wifi: mac80211: remove cipher scheme support wifi: nl80211: fix typo in comment wifi: virt_wifi: fix typo in comment rtw89: add new state to CFO state machine for UL-OFDMA rtw89: 8852c: add trigger frame counter ieee80211: add trigger frame definition wifi: wfx: Remove redundant NULL check before release_firmware() call wifi: rtw89: support MULTI_BSSID and correct BSSID mask of H2C wifi: ray_cs: Drop useless status variable in parse_addr() wifi: ray_cs: Utilize strnlen() in parse_addr() wifi: rtw88: use %*ph to print small buffer wifi: wilc1000: add IGTK support wifi: wilc1000: add WPA3 SAE support wifi: wilc1000: remove WEP security support wifi: wilc1000: use correct sequence of RESET for chip Power-UP/Down wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c() wifi: rtw88: Fix Sparse warning for rtw8821c_hw_spec wifi: rtw88: Fix Sparse warning for rtw8723d_hw_spec ... ==================== Link: https://lore.kernel.org/r/20220610142838.330862-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/wireless/realtek')
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.c8
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c5
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723de.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723de.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821ce.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821ce.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822be.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822be.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822ce.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822ce.h10
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.c7
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.h8
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c56
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h45
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c24
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c9
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c24
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c27
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/sar.c140
38 files changed, 349 insertions, 105 deletions
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c
index 901cdfe3723c..0b1bc04cb6ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -329,8 +329,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp,
tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
- if (!buffer || copy_from_user(tmp, buffer, tmp_len))
- return count;
+ if (copy_from_user(tmp, buffer, tmp_len))
+ return -EFAULT;
tmp[tmp_len] = '\0';
@@ -340,8 +340,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp,
&h2c_data[4], &h2c_data[5],
&h2c_data[6], &h2c_data[7]);
- if (h2c_len <= 0)
- return count;
+ if (h2c_len == 0)
+ return -EINVAL;
for (i = 0; i < h2c_len; i++)
h2c_data_packed[i] = (u8)h2c_data[i];
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index 1a52ff585fbc..7cde6bcf253b 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -269,11 +269,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
for (i = 0 ; i < buf_size ; i += 8) {
if (i % page_size == 0)
seq_printf(m, "PAGE %d\n", (i + offset) / page_size);
- seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
- *(buf + i), *(buf + i + 1),
- *(buf + i + 2), *(buf + i + 3),
- *(buf + i + 4), *(buf + i + 5),
- *(buf + i + 6), *(buf + i + 7));
+ seq_printf(m, "%8ph\n", buf + i);
}
vfree(buf);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index efabd5b1bf5b..a44b1810165d 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1383,9 +1383,12 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool hw_scan)
{
- struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+ struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL;
u32 config = 0;
+ if (!rtwvif)
+ return;
+
clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 93cce44df531..993bd6b1d723 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -2701,7 +2701,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
{0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
};
-struct rtw_chip_info rtw8723d_hw_spec = {
+const struct rtw_chip_info rtw8723d_hw_spec = {
.ops = &rtw8723d_ops,
.id = RTW_CHIP_TYPE_8723D,
.fw_name = "rtw88/rtw8723d_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 41d35174a542..4641f6e047b4 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -72,6 +72,8 @@ struct rtw8723d_efuse {
struct rtw8723de_efuse e;
};
+extern const struct rtw_chip_info rtw8723d_hw_spec;
+
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c
index 2dd689441e8d..abbaafa32851 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723de.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c
@@ -5,7 +5,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
-#include "rtw8723de.h"
+#include "rtw8723d.h"
static const struct pci_device_id rtw_8723de_id_table[] = {
{
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.h b/drivers/net/wireless/realtek/rtw88/rtw8723de.h
deleted file mode 100644
index 2b4894846a07..000000000000
--- a/drivers/net/wireless/realtek/rtw88/rtw8723de.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019 Realtek Corporation
- */
-
-#ifndef __RTW_8723DE_H_
-#define __RTW_8723DE_H_
-
-extern struct rtw_chip_info rtw8723d_hw_spec;
-
-#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index ffee39ea5df6..42841f5d502c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -1877,7 +1877,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
{0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
};
-struct rtw_chip_info rtw8821c_hw_spec = {
+const struct rtw_chip_info rtw8821c_hw_spec = {
.ops = &rtw8821c_ops,
.id = RTW_CHIP_TYPE_8821C,
.fw_name = "rtw88/rtw8821c_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index d9fbddd7b0f3..2698801fc35d 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -84,6 +84,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
}
+extern const struct rtw_chip_info rtw8821c_hw_spec;
+
#define rtw_write32s_mask(rtwdev, addr, mask, data) \
do { \
BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c
index 56d22f9de904..f3d971feda04 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c
@@ -5,7 +5,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
-#include "rtw8821ce.h"
+#include "rtw8821c.h"
static const struct pci_device_id rtw_8821ce_id_table[] = {
{
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.h b/drivers/net/wireless/realtek/rtw88/rtw8821ce.h
deleted file mode 100644
index 54142acca534..000000000000
--- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019 Realtek Corporation
- */
-
-#ifndef __RTW_8821CE_H_
-#define __RTW_8821CE_H_
-
-extern struct rtw_chip_info rtw8821c_hw_spec;
-
-#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index dccd722b8e62..321848870561 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -2497,7 +2497,7 @@ static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
[EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
};
-struct rtw_chip_info rtw8822b_hw_spec = {
+const struct rtw_chip_info rtw8822b_hw_spec = {
.ops = &rtw8822b_ops,
.id = RTW_CHIP_TYPE_8822B,
.fw_name = "rtw88/rtw8822b_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
index 3fff8b881854..01d3644e0c94 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
@@ -187,4 +187,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define REG_ANTWT 0x1904
#define REG_IQKFAILMSK 0x1bf0
+extern const struct rtw_chip_info rtw8822b_hw_spec;
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.c b/drivers/net/wireless/realtek/rtw88/rtw8822be.c
index 62ee7e62cac0..4994950776cd 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822be.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822be.c
@@ -5,7 +5,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
-#include "rtw8822be.h"
+#include "rtw8822b.h"
static const struct pci_device_id rtw_8822be_id_table[] = {
{
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.h b/drivers/net/wireless/realtek/rtw88/rtw8822be.h
deleted file mode 100644
index 6668460d664d..000000000000
--- a/drivers/net/wireless/realtek/rtw88/rtw8822be.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019 Realtek Corporation
- */
-
-#ifndef __RTW_8822BE_H_
-#define __RTW_8822BE_H_
-
-extern struct rtw_chip_info rtw8822b_hw_spec;
-
-#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index c043b5c520b9..09f9e4adcf34 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -5310,7 +5310,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = {
{0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
};
-struct rtw_chip_info rtw8822c_hw_spec = {
+const struct rtw_chip_info rtw8822c_hw_spec = {
.ops = &rtw8822c_ops,
.id = RTW_CHIP_TYPE_8822C,
.fw_name = "rtw88/rtw8822c_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
index 8201955e1f21..479d5d769c52 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -118,6 +118,8 @@ enum rtw8822c_dpk_one_shot_action {
void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev,
const struct rtw_table *tbl);
+extern const struct rtw_chip_info rtw8822c_hw_spec;
+
#define RTW_DECL_TABLE_DPK(name) \
const struct rtw_table name ## _tbl = { \
.data = name, \
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c
index 3845b1333dc3..e26c6bc82936 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c
@@ -5,7 +5,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
-#include "rtw8822ce.h"
+#include "rtw8822c.h"
static const struct pci_device_id rtw_8822ce_id_table[] = {
{
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h b/drivers/net/wireless/realtek/rtw88/rtw8822ce.h
deleted file mode 100644
index fee32d7a4504..000000000000
--- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019 Realtek Corporation
- */
-
-#ifndef __RTW_8822CE_H_
-#define __RTW_8822CE_H_
-
-extern struct rtw_chip_info rtw8822c_hw_spec;
-
-#endif
diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
index 8a26adeb23fb..db3c55f0ccd0 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.c
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
@@ -602,11 +602,18 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
u8 bss_color = vif->bss_conf.he_bss_color.color;
+ u8 bss_mask;
+
+ if (vif->bss_conf.nontransmitted)
+ bss_mask = RTW89_BSSID_MATCH_5_BYTES;
+ else
+ bss_mask = RTW89_BSSID_MATCH_ALL;
FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx);
FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset);
FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len);
FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid);
+ FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask);
FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx);
FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color);
diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h
index a3931d3e40d2..74a6c4748d64 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.h
+++ b/drivers/net/wireless/realtek/rtw89/cam.h
@@ -9,6 +9,9 @@
#define RTW89_SEC_CAM_LEN 20
+#define RTW89_BSSID_MATCH_ALL GENMASK(5, 0)
+#define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0)
+
static inline void FWCMD_SET_ADDR_IDX(void *cmd, u32 value)
{
le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(7, 0));
@@ -309,6 +312,11 @@ static inline void FWCMD_SET_ADDR_BSSID_BB_SEL(void *cmd, u32 value)
le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(1));
}
+static inline void FWCMD_SET_ADDR_BSSID_MASK(void *cmd, u32 value)
+{
+ le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(7, 2));
+}
+
static inline void FWCMD_SET_ADDR_BSSID_BSS_COLOR(void *cmd, u32 value)
{
le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(13, 8));
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index a6a90572e74b..d2f2a3d65ef6 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1343,6 +1343,47 @@ struct rtw89_vif_rx_stats_iter_data {
const u8 *bssid;
};
+static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb)
+{
+ struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data;
+ u8 *pos, *end, type;
+ u16 aid;
+
+ if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) ||
+ rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION ||
+ rtwvif->net_type == RTW89_NET_TYPE_NO_LINK)
+ return;
+
+ type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK);
+ if (type != IEEE80211_TRIGGER_TYPE_BASIC)
+ return;
+
+ end = (u8 *)tf + skb->len;
+ pos = tf->variable;
+
+ while (end - pos >= RTW89_TF_BASIC_USER_INFO_SZ) {
+ aid = RTW89_GET_TF_USER_INFO_AID12(pos);
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "[TF] aid: %d, ul_mcs: %d, rua: %d\n",
+ aid, RTW89_GET_TF_USER_INFO_UL_MCS(pos),
+ RTW89_GET_TF_USER_INFO_RUA(pos));
+
+ if (aid == RTW89_TF_PAD)
+ break;
+
+ if (aid == vif->bss_conf.aid) {
+ rtwvif->stats.rx_tf_acc++;
+ rtwdev->stats.rx_tf_acc++;
+ break;
+ }
+
+ pos += RTW89_TF_BASIC_USER_INFO_SZ;
+ }
+}
+
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -1355,6 +1396,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
const u8 *bssid = iter_data->bssid;
+ if (ieee80211_is_trigger(hdr->frame_control)) {
+ rtw89_stats_trigger_frame(rtwdev, vif, skb);
+ return;
+ }
+
if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
return;
@@ -1608,7 +1654,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
if (rtwdev->scanning &&
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
- u8 chan = hal->current_channel;
+ u8 chan = hal->current_primary_channel;
u8 band = hal->current_band_type;
enum nl80211_band nl_band;
@@ -2023,6 +2069,8 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev,
stats->rx_unicast = 0;
stats->tx_cnt = 0;
stats->rx_cnt = 0;
+ stats->rx_tf_periodic = stats->rx_tf_acc;
+ stats->rx_tf_acc = 0;
if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv)
return true;
@@ -2875,7 +2923,10 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif, bool hw_scan)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
+
+ if (!rtwvif)
+ return;
ether_addr_copy(rtwvif->mac_addr, vif->addr);
rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
@@ -3008,6 +3059,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index e8a77225a90f..239d47d0ec6d 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -55,6 +55,16 @@ enum htc_om_channel_width {
#define RTW89_HTC_MASK_HTC_OM_DL_MU_MIMO_RR BIT(16)
#define RTW89_HTC_MASK_HTC_OM_UL_MU_DATA_DIS BIT(17)
+#define RTW89_TF_PAD GENMASK(11, 0)
+#define RTW89_TF_BASIC_USER_INFO_SZ 6
+
+#define RTW89_GET_TF_USER_INFO_AID12(data) \
+ le32_get_bits(*((const __le32 *)(data)), GENMASK(11, 0))
+#define RTW89_GET_TF_USER_INFO_RUA(data) \
+ le32_get_bits(*((const __le32 *)(data)), GENMASK(19, 12))
+#define RTW89_GET_TF_USER_INFO_UL_MCS(data) \
+ le32_get_bits(*((const __le32 *)(data)), GENMASK(24, 21))
+
enum rtw89_subband {
RTW89_CH_2G = 0,
RTW89_CH_5G_BAND_1 = 1,
@@ -943,6 +953,10 @@ struct rtw89_traffic_stats {
u32 rx_throughput;
u32 tx_throughput_raw;
u32 rx_throughput_raw;
+
+ u32 rx_tf_acc;
+ u32 rx_tf_periodic;
+
enum rtw89_tfc_lv tx_tfc_lv;
enum rtw89_tfc_lv rx_tfc_lv;
struct ewma_tp tx_ewma_tp;
@@ -2550,9 +2564,24 @@ enum rtw89_sar_sources {
RTW89_SAR_SOURCE_NR,
};
+enum rtw89_sar_subband {
+ RTW89_SAR_2GHZ_SUBBAND,
+ RTW89_SAR_5GHZ_SUBBAND_1_2, /* U-NII-1 and U-NII-2 */
+ RTW89_SAR_5GHZ_SUBBAND_2_E, /* U-NII-2-Extended */
+ RTW89_SAR_5GHZ_SUBBAND_3, /* U-NII-3 */
+ RTW89_SAR_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */
+ RTW89_SAR_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */
+ RTW89_SAR_6GHZ_SUBBAND_6, /* U-NII-6 */
+ RTW89_SAR_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */
+ RTW89_SAR_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */
+ RTW89_SAR_6GHZ_SUBBAND_8, /* U-NII-8 */
+
+ RTW89_SAR_SUBBAND_NR,
+};
+
struct rtw89_sar_cfg_common {
- bool set[RTW89_SUBBAND_NR];
- s32 cfg[RTW89_SUBBAND_NR];
+ bool set[RTW89_SAR_SUBBAND_NR];
+ s32 cfg[RTW89_SAR_SUBBAND_NR];
};
struct rtw89_sar_info {
@@ -2646,6 +2675,10 @@ struct rtw89_lck_info {
u8 thermal[RF_PATH_MAX];
};
+struct rtw89_rx_dck_info {
+ u8 thermal[RF_PATH_MAX];
+};
+
struct rtw89_iqk_info {
bool lok_cor_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
bool lok_fin_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
@@ -2776,13 +2809,20 @@ enum rtw89_multi_cfo_mode {
enum rtw89_phy_cfo_status {
RTW89_PHY_DCFO_STATE_NORMAL = 0,
RTW89_PHY_DCFO_STATE_ENHANCE = 1,
+ RTW89_PHY_DCFO_STATE_HOLD = 2,
RTW89_PHY_DCFO_STATE_MAX
};
+enum rtw89_phy_cfo_ul_ofdma_acc_mode {
+ RTW89_CFO_UL_OFDMA_ACC_DISABLE = 0,
+ RTW89_CFO_UL_OFDMA_ACC_ENABLE = 1
+};
+
struct rtw89_cfo_tracking_info {
u16 cfo_timer_ms;
bool cfo_trig_by_timer_en;
enum rtw89_phy_cfo_status phy_cfo_status;
+ enum rtw89_phy_cfo_ul_ofdma_acc_mode cfo_ul_ofdma_acc_mode;
u8 phy_cfo_trk_cnt;
bool is_adjust;
enum rtw89_multi_cfo_mode rtw89_multi_cfo_mode;
@@ -3125,6 +3165,7 @@ struct rtw89_dev {
struct rtw89_dpk_info dpk;
struct rtw89_mcc_info mcc;
struct rtw89_lck_info lck;
+ struct rtw89_rx_dck_info rx_dck;
bool is_tssi_mode[RF_PATH_MAX];
bool is_bt_iqk_timeout;
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 7820bc3ab3b4..f00f81916f2f 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -2376,7 +2376,8 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v)
seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n",
stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv,
stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv);
- seq_printf(m, "Beacon: %u\n", pkt_stat->beacon_nr);
+ seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr,
+ stats->rx_tf_periodic);
seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len,
stats->rx_avg_len);
diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h
index de72155ad1fe..561b04faf703 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.h
+++ b/drivers/net/wireless/realtek/rtw89/debug.h
@@ -24,6 +24,7 @@ enum rtw89_debug_mask {
RTW89_DBG_BTC = BIT(13),
RTW89_DBG_BF = BIT(14),
RTW89_DBG_HW_SCAN = BIT(15),
+ RTW89_DBG_SAR = BIT(16),
};
enum rtw89_debug_mac_reg_sel {
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 4718aced1428..2d9c3157d878 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -2257,7 +2257,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
list_add_tail(&ch_info->list, &chan_list);
off_chan_time += ch_info->period;
}
- rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
+ ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
out:
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
@@ -2339,6 +2339,9 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
rtwvif->scan_req = NULL;
rtwvif->scan_ies = NULL;
rtwdev->scan_info.scanning_vif = NULL;
+
+ if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK)
+ rtw89_store_op_chan(rtwdev, false);
}
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
@@ -2365,20 +2368,27 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
if (ret)
goto out;
}
- rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif);
+ ret = rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif);
out:
return ret;
}
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev)
+void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
{
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
struct rtw89_hal *hal = &rtwdev->hal;
- scan_info->op_pri_ch = hal->current_primary_channel;
- scan_info->op_chan = hal->current_channel;
- scan_info->op_bw = hal->current_band_width;
- scan_info->op_band = hal->current_band_type;
+ if (backup) {
+ scan_info->op_pri_ch = hal->current_primary_channel;
+ scan_info->op_chan = hal->current_channel;
+ scan_info->op_bw = hal->current_band_width;
+ scan_info->op_band = hal->current_band_type;
+ } else {
+ hal->current_primary_channel = scan_info->op_pri_ch;
+ hal->current_channel = scan_info->op_chan;
+ hal->current_band_width = scan_info->op_bw;
+ hal->current_band_type = scan_info->op_band;
+ }
}
#define H2C_FW_CPU_EXCEPTION_LEN 4
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 95a55c4213db..e75ad22aa85d 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -2633,17 +2633,14 @@ 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_store_op_chan(struct rtw89_dev *rtwdev);
+void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup);
void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
bool aborted);
int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
bool enable);
-void rtw89_hw_scan_status_report(struct rtw89_dev *rtwdev, struct sk_buff *skb);
-void rtw89_hw_scan_chan_switch(struct rtw89_dev *rtwdev, struct sk_buff *skb);
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 3cf892912c1d..93124b815825 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -3681,17 +3681,20 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
rtw89_hw_scan_complete(rtwdev, vif, false);
break;
case RTW89_SCAN_ENTER_CH_NOTIFY:
- if (rtw89_is_op_chan(rtwdev, band, chan))
+ hal->prev_band_type = hal->current_band_type;
+ hal->current_band_type = band;
+ hal->prev_primary_channel = hal->current_primary_channel;
+ hal->current_primary_channel = chan;
+ hal->current_channel = chan;
+ hal->current_band_width = RTW89_CHANNEL_WIDTH_20;
+ if (rtw89_is_op_chan(rtwdev, band, chan)) {
+ rtw89_store_op_chan(rtwdev, false);
ieee80211_wake_queues(rtwdev->hw);
+ }
break;
default:
return;
}
-
- hal->prev_band_type = hal->current_band_type;
- hal->prev_primary_channel = hal->current_channel;
- hal->current_channel = chan;
- hal->current_band_type = band;
}
static void
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 9f511c8d8a37..f66619354734 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -666,6 +666,7 @@ enum mac_ax_err_info {
MAC_AX_ERR_L2_ERR_APB_BBRF_TO_RX4281 = 0x2360,
MAC_AX_ERR_L2_ERR_APB_BBRF_TO_OTHERS = 0x2370,
MAC_AX_ERR_L2_RESET_DONE = 0x2400,
+ MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT = 0x2599,
MAC_AX_ERR_CPU_EXCEPTION = 0x3000,
MAC_AX_ERR_ASSERTION = 0x4000,
MAC_AX_GET_ERR_MAX,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index f24e4a208376..6d0c62c545a7 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -350,7 +350,7 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw89_phy_set_bss_color(rtwdev, vif);
rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
rtw89_mac_port_update(rtwdev, rtwvif);
- rtw89_store_op_chan(rtwdev);
+ rtw89_store_op_chan(rtwdev, true);
} else {
/* Abort ongoing scan if cancel_scan isn't issued
* when disconnected by peer
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 0ef7821b2e0f..25872dfb4da1 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -738,6 +738,9 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev)
if (unlikely(isrs.halt_c2h_isrs & B_AX_HALT_C2H_INT_EN))
rtw89_ser_notify(rtwdev, rtw89_mac_get_err_status(rtwdev));
+ if (unlikely(isrs.halt_c2h_isrs & B_AX_WDT_TIMEOUT_INT_EN))
+ rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT);
+
if (unlikely(rtwpci->under_recovery))
goto enable_intr;
@@ -3126,7 +3129,7 @@ static void rtw89_pci_recovery_intr_mask_v1(struct rtw89_dev *rtwdev)
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
rtwpci->ind_intrs = B_AX_HS0ISR_IND_INT_EN;
- rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+ rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
rtwpci->intrs[0] = 0;
rtwpci->intrs[1] = 0;
}
@@ -3138,7 +3141,7 @@ static void rtw89_pci_default_intr_mask_v1(struct rtw89_dev *rtwdev)
rtwpci->ind_intrs = B_AX_HCI_AXIDMA_INT_EN |
B_AX_HS1ISR_IND_INT_EN |
B_AX_HS0ISR_IND_INT_EN;
- rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+ rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN |
B_AX_RXDMA_INT_EN |
B_AX_RXP1DMA_INT_EN |
@@ -3155,7 +3158,7 @@ static void rtw89_pci_low_power_intr_mask_v1(struct rtw89_dev *rtwdev)
rtwpci->ind_intrs = B_AX_HS1ISR_IND_INT_EN |
B_AX_HS0ISR_IND_INT_EN;
- rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+ rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
rtwpci->intrs[0] = 0;
rtwpci->intrs[1] = B_AX_GPIO18_INT_EN;
}
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index bb585ed19190..a118647213e3 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -94,6 +94,7 @@
/* Interrupts */
#define R_AX_HIMR0 0x01A0
+#define B_AX_WDT_TIMEOUT_INT_EN BIT(22)
#define B_AX_HALT_C2H_INT_EN BIT(21)
#define R_AX_HISR0 0x01A4
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 762cdba9d3cf..217aacb6e8c1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -2151,6 +2151,7 @@ static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev)
cfo->cfo_trig_by_timer_en = false;
cfo->phy_cfo_trk_cnt = 0;
cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
+ cfo->cfo_ul_ofdma_acc_mode = RTW89_CFO_UL_OFDMA_ACC_ENABLE;
}
static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
@@ -2419,6 +2420,13 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
{
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
struct rtw89_traffic_stats *stats = &rtwdev->stats;
+ bool is_ul_ofdma = false, ofdma_acc_en = false;
+
+ if (stats->rx_tf_periodic > CFO_TF_CNT_TH)
+ is_ul_ofdma = true;
+ if (cfo->cfo_ul_ofdma_acc_mode == RTW89_CFO_UL_OFDMA_ACC_ENABLE &&
+ is_ul_ofdma)
+ ofdma_acc_en = true;
switch (cfo->phy_cfo_status) {
case RTW89_PHY_DCFO_STATE_NORMAL:
@@ -2430,16 +2438,26 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
}
break;
case RTW89_PHY_DCFO_STATE_ENHANCE:
- if (cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT) {
+ if (stats->tx_throughput <= CFO_TP_LOWER)
+ cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
+ else if (ofdma_acc_en &&
+ cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT)
+ cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_HOLD;
+ else
+ cfo->phy_cfo_trk_cnt++;
+
+ if (cfo->phy_cfo_status == RTW89_PHY_DCFO_STATE_NORMAL) {
cfo->phy_cfo_trk_cnt = 0;
cfo->cfo_trig_by_timer_en = false;
}
- if (cfo->cfo_trig_by_timer_en == 1)
- cfo->phy_cfo_trk_cnt++;
+ break;
+ case RTW89_PHY_DCFO_STATE_HOLD:
if (stats->tx_throughput <= CFO_TP_LOWER) {
cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
cfo->phy_cfo_trk_cnt = 0;
cfo->cfo_trig_by_timer_en = false;
+ } else {
+ cfo->phy_cfo_trk_cnt++;
}
break;
default:
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 291660154d58..e20636f54b55 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -62,6 +62,7 @@
#define CFO_COMP_PERIOD 250
#define CFO_COMP_WEIGHT 8
#define MAX_CFO_TOLERANCE 30
+#define CFO_TF_CNT_TH 300
#define CCX_MAX_PERIOD 2097
#define CCX_MAX_PERIOD_UNIT 32
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 64840c8d9efe..b697aef2faf2 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -1861,6 +1861,7 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev)
{
rtw8852c_dpk_track(rtwdev);
rtw8852c_lck_track(rtwdev);
+ rtw8852c_rx_dck_track(rtwdev);
}
static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index dfb9caba9bc4..4186d825d19b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -3864,6 +3864,7 @@ void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe)
{
+ struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck;
u8 path, kpath;
u32 rf_reg5;
@@ -3883,6 +3884,7 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a
rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
_set_rx_dck(rtwdev, phy, path, is_afe);
+ rx_dck->thermal[path] = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
if (rtwdev->is_tssi_mode[path])
@@ -3891,6 +3893,31 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a
}
}
+#define RTW8852C_RX_DCK_TH 8
+
+void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck;
+ u8 cur_thermal;
+ int delta;
+ int path;
+
+ for (path = 0; path < RF_PATH_NUM_8852C; path++) {
+ cur_thermal =
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
+ delta = abs((int)cur_thermal - rx_dck->thermal[path]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[RX_DCK] path=%d current thermal=0x%x delta=0x%x\n",
+ path, cur_thermal, delta);
+
+ if (delta >= RTW8852C_RX_DCK_TH) {
+ rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false);
+ return;
+ }
+ }
+}
+
void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
u32 tx_en;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
index c32756f0c01a..5118a49da8d3 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
@@ -12,6 +12,7 @@ void rtw8852c_rck(struct rtw89_dev *rtwdev);
void rtw8852c_dack(struct rtw89_dev *rtwdev);
void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe);
+void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev);
void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
void rtw8852c_dpk_track(struct rtw89_dev *rtwdev);
void rtw8852c_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c
index 097c87899cea..eb2d3ec28775 100644
--- a/drivers/net/wireless/realtek/rtw89/sar.c
+++ b/drivers/net/wireless/realtek/rtw89/sar.c
@@ -5,15 +5,122 @@
#include "debug.h"
#include "sar.h"
+static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
+ u32 center_freq)
+{
+ switch (center_freq) {
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_SAR,
+ "center freq: %u to SAR subband is unhandled\n",
+ center_freq);
+ fallthrough;
+ case 2412 ... 2484:
+ return RTW89_SAR_2GHZ_SUBBAND;
+ case 5180 ... 5320:
+ return RTW89_SAR_5GHZ_SUBBAND_1_2;
+ case 5500 ... 5720:
+ return RTW89_SAR_5GHZ_SUBBAND_2_E;
+ case 5745 ... 5825:
+ return RTW89_SAR_5GHZ_SUBBAND_3;
+ case 5955 ... 6155:
+ return RTW89_SAR_6GHZ_SUBBAND_5_L;
+ case 6175 ... 6415:
+ return RTW89_SAR_6GHZ_SUBBAND_5_H;
+ case 6435 ... 6515:
+ return RTW89_SAR_6GHZ_SUBBAND_6;
+ case 6535 ... 6695:
+ return RTW89_SAR_6GHZ_SUBBAND_7_L;
+ case 6715 ... 6855:
+ return RTW89_SAR_6GHZ_SUBBAND_7_H;
+
+ /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H
+ * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with
+ * struct rtw89_sar_span in the following.
+ */
+
+ case 6895 ... 7115:
+ return RTW89_SAR_6GHZ_SUBBAND_8;
+ }
+}
+
+struct rtw89_sar_span {
+ enum rtw89_sar_subband subband_low;
+ enum rtw89_sar_subband subband_high;
+};
+
+#define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high)
+
+#define RTW89_SAR_6GHZ_SPAN_HEAD 6145
+#define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \
+ ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2)
+
+#define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \
+ [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \
+ .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
+ .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
+ }
+
+/* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR
+ * subbands. In the following, we describe each of them with rtw89_sar_span.
+ */
+static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
+ RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H),
+ RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H),
+ RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
+};
+
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
{
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
- enum rtw89_subband subband = rtwdev->hal.current_subband;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ enum rtw89_band band = hal->current_band_type;
+ u32 center_freq = hal->current_freq;
+ const struct rtw89_sar_span *span = NULL;
+ enum rtw89_sar_subband subband_l, subband_h;
+ int idx;
+
+ if (band == RTW89_BAND_6G) {
+ idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
+ /* To decrease size of rtw89_sar_overlapping_6ghz[],
+ * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
+ * to make first span as index 0 of the table. So, if center
+ * frequency is less than the first one, it will get netative.
+ */
+ if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz))
+ span = &rtw89_sar_overlapping_6ghz[idx];
+ }
+
+ if (span && RTW89_SAR_SPAN_VALID(span)) {
+ subband_l = span->subband_low;
+ subband_h = span->subband_high;
+ } else {
+ subband_l = rtw89_sar_get_subband(rtwdev, center_freq);
+ subband_h = subband_l;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_SAR,
+ "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n",
+ band, center_freq, subband_l, subband_h);
- if (!rtwsar->set[subband])
+ if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h])
return -ENODATA;
- *cfg = rtwsar->cfg[subband];
+ if (!rtwsar->set[subband_l])
+ *cfg = rtwsar->cfg[subband_h];
+ else if (!rtwsar->set[subband_h])
+ *cfg = rtwsar->cfg[subband_l];
+ else
+ *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]);
+
return 0;
}
@@ -128,21 +235,20 @@ exit:
return ret;
}
-static const u8 rtw89_common_sar_subband_map[] = {
- RTW89_CH_2G,
- RTW89_CH_5G_BAND_1,
- RTW89_CH_5G_BAND_3,
- RTW89_CH_5G_BAND_4,
-};
-
static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = {
{ .start_freq = 2412, .end_freq = 2484, },
{ .start_freq = 5180, .end_freq = 5320, },
{ .start_freq = 5500, .end_freq = 5720, },
{ .start_freq = 5745, .end_freq = 5825, },
+ { .start_freq = 5955, .end_freq = 6155, },
+ { .start_freq = 6175, .end_freq = 6415, },
+ { .start_freq = 6435, .end_freq = 6515, },
+ { .start_freq = 6535, .end_freq = 6695, },
+ { .start_freq = 6715, .end_freq = 6875, },
+ { .start_freq = 6875, .end_freq = 7115, },
};
-static_assert(ARRAY_SIZE(rtw89_common_sar_subband_map) ==
+static_assert(RTW89_SAR_SUBBAND_NR ==
ARRAY_SIZE(rtw89_common_sar_freq_ranges));
const struct cfg80211_sar_capa rtw89_sar_capa = {
@@ -159,7 +265,6 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
u8 fct;
u32 freq_start;
u32 freq_end;
- u32 band;
s32 power;
u32 i, idx;
@@ -175,15 +280,14 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
freq_start = rtw89_common_sar_freq_ranges[idx].start_freq;
freq_end = rtw89_common_sar_freq_ranges[idx].end_freq;
- band = rtw89_common_sar_subband_map[idx];
power = sar->sub_specs[i].power;
- rtw89_info(rtwdev, "On freq %u to %u, ", freq_start, freq_end);
- rtw89_info(rtwdev, "set SAR power limit %d (unit: 1/%lu dBm)\n",
- power, BIT(fct));
+ rtw89_debug(rtwdev, RTW89_DBG_SAR,
+ "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n",
+ freq_start, freq_end, power, BIT(fct));
- sar_common.set[band] = true;
- sar_common.cfg[band] = power;
+ sar_common.set[idx] = true;
+ sar_common.cfg[idx] = power;
}
return rtw89_apply_sar_common(rtwdev, &sar_common);