* [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs
@ 2025-11-04 9:14 pkshih
2025-11-04 9:14 ` [PATCH rtw-next 1/8] wifi: rtw89: pci: add to read PCI configuration space from common code pkshih
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
First three patches are to add diagnosis to debugfs. This feature is to
provide hints to see if MAC hardware went wrong to assist debugging quickly.
Patches 6-8 are related to monitor mode. First is to support injection with
rate/bw/GI. Second is to do calibration on the channel running monitor mode
to have better receiving performance. Third is to configure RX antenna, so
we can test RX performance individually.
Others are patch 4 which implements extension of thermal value programmed
in efuse, and patch 5 fixes Coverity warnings.
Kuan-Chung Chen (1):
wifi: rtw89: phy: fix out-of-bounds access in
rtw89_phy_read_txpwr_limit()
Ping-Ke Shih (7):
wifi: rtw89: pci: add to read PCI configuration space from common code
wifi: rtw89: fw: parse firmware element of DIAG_MAC
wifi: rtw89: debug: add parser to diagnose along DIAG_MAC fw element
wifi: rtw89: 8852c: add compensation of thermal value from efuse
calibration
wifi: rtw89: consider data rate/bandwidth/GI for injected packets
wifi: rtw89: do RF calibration once setting channel when running pure
monitor mode
wifi: rtw89: configure RX antenna if chips can support
drivers/net/wireless/realtek/rtw89/core.c | 85 +++++
drivers/net/wireless/realtek/rtw89/core.h | 17 +
drivers/net/wireless/realtek/rtw89/debug.c | 299 ++++++++++++++++++
drivers/net/wireless/realtek/rtw89/fw.c | 15 +
drivers/net/wireless/realtek/rtw89/fw.h | 6 +
drivers/net/wireless/realtek/rtw89/mac.h | 2 -
drivers/net/wireless/realtek/rtw89/mac80211.c | 9 +
drivers/net/wireless/realtek/rtw89/pci.c | 16 +
drivers/net/wireless/realtek/rtw89/phy.c | 20 ++
.../wireless/realtek/rtw89/rtw8852b_common.c | 6 +-
drivers/net/wireless/realtek/rtw89/rtw8852c.c | 41 ++-
drivers/net/wireless/realtek/rtw89/rtw8922a.c | 12 +-
12 files changed, 517 insertions(+), 11 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH rtw-next 1/8] wifi: rtw89: pci: add to read PCI configuration space from common code
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 2/8] wifi: rtw89: fw: parse firmware element of DIAG_MAC pkshih
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
Normally only access PCI device in pci.c. However for debug purpose,
a set of registers predefined in firmware element including PCI
configuration space should be read for diagnosis.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 13 +++++++++++++
drivers/net/wireless/realtek/rtw89/mac.h | 2 --
drivers/net/wireless/realtek/rtw89/pci.c | 16 ++++++++++++++++
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 97cb0e5f0898..fd0e1a68ecc4 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -39,6 +39,8 @@ extern const struct ieee80211_ops rtw89_ops;
#define RFREG_MASK 0xfffff
#define INV_RF_DATA 0xffffffff
#define BYPASS_CR_DATA 0xbabecafe
+#define RTW89_R32_EA 0xEAEAEAEA
+#define RTW89_R32_DEAD 0xDEADBEEF
#define RTW89_TRACK_WORK_PERIOD round_jiffies_relative(HZ * 2)
#define RTW89_TRACK_PS_WORK_PERIOD msecs_to_jiffies(100)
@@ -3654,6 +3656,8 @@ struct rtw89_hci_ops {
void (*write16)(struct rtw89_dev *rtwdev, u32 addr, u16 data);
void (*write32)(struct rtw89_dev *rtwdev, u32 addr, u32 data);
+ u32 (*read32_pci_cfg)(struct rtw89_dev *rtwdev, u32 addr);
+
int (*mac_pre_init)(struct rtw89_dev *rtwdev);
int (*mac_pre_deinit)(struct rtw89_dev *rtwdev);
int (*mac_post_init)(struct rtw89_dev *rtwdev);
@@ -6634,6 +6638,15 @@ rtw89_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
mutex_unlock(&rtwdev->rf_mutex);
}
+static inline u32 rtw89_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr)
+{
+ if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE ||
+ !rtwdev->hci.ops->read32_pci_cfg)
+ return RTW89_R32_EA;
+
+ return rtwdev->hci.ops->read32_pci_cfg(rtwdev, addr);
+}
+
static inline struct ieee80211_txq *rtw89_txq_to_txq(struct rtw89_txq *rtwtxq)
{
void *p = rtwtxq;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 46302f4aa3d9..d9c854c37452 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -574,8 +574,6 @@ enum rtw89_mac_bf_rrsc_rate {
RTW89_MAC_BF_RRSC_MAX = 32
};
-#define RTW89_R32_EA 0xEAEAEAEA
-#define RTW89_R32_DEAD 0xDEADBEEF
#define MAC_REG_POOL_COUNT 10
#define ACCESS_CMAC(_addr) \
({typeof(_addr) __addr = (_addr); \
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 0ee5f8579447..8fe9f6208c54 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -2064,6 +2064,20 @@ static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data)
writel(data, rtwpci->mmap + addr);
}
+static u32 rtw89_pci_ops_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr)
+{
+ struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ struct pci_dev *pdev = rtwpci->pdev;
+ u32 value;
+ int ret;
+
+ ret = pci_read_config_dword(pdev, addr, &value);
+ if (ret)
+ return RTW89_R32_EA;
+
+ return value;
+}
+
static void rtw89_pci_ctrl_dma_trx(struct rtw89_dev *rtwdev, bool enable)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
@@ -4683,6 +4697,8 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
.write16 = rtw89_pci_ops_write16,
.write32 = rtw89_pci_ops_write32,
+ .read32_pci_cfg = rtw89_pci_ops_read32_pci_cfg,
+
.mac_pre_init = rtw89_pci_ops_mac_pre_init,
.mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit,
.mac_post_init = rtw89_pci_ops_mac_post_init,
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 2/8] wifi: rtw89: fw: parse firmware element of DIAG_MAC
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
2025-11-04 9:14 ` [PATCH rtw-next 1/8] wifi: rtw89: pci: add to read PCI configuration space from common code pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 3/8] wifi: rtw89: debug: add parser to diagnose along DIAG_MAC fw element pkshih
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
The firmware element ID 28 is a set of rules to diagnose if MAC get
abnormal. The latter patch will use these rules via debugfs to know
the status.
The element contains rules with their textual messages shown as below:
+------------------------------------+
| |
| +-----------+ |
| | rule_size |-------|----------+
+----------------+-----------+-------+ -- |
| rule[0] | \ |
| rule[1] | | <---+
| : | /
+------------------------------------+ --
| msg[0] msg[1] | each msg has variable length
| msg[2] msg[3] ... | (with address align 2)
| ... |
+------------------------------------+
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 1 +
drivers/net/wireless/realtek/rtw89/fw.c | 15 +++++++++++++++
drivers/net/wireless/realtek/rtw89/fw.h | 6 ++++++
3 files changed, 22 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index fd0e1a68ecc4..01bfc5b473f5 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4707,6 +4707,7 @@ struct rtw89_fw_elm_info {
struct rtw89_phy_rfk_log_fmt *rfk_log_fmt;
const struct rtw89_regd_data *regd;
const struct rtw89_fw_element_hdr *afe;
+ const struct rtw89_fw_element_hdr *diag_mac;
};
enum rtw89_fw_mss_dev_type {
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index cb431c8a65ac..38b9654b7eec 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1298,6 +1298,18 @@ int rtw89_build_afe_pwr_seq_from_elm(struct rtw89_dev *rtwdev,
return 0;
}
+static
+int rtw89_recognize_diag_mac_from_elm(struct rtw89_dev *rtwdev,
+ const struct rtw89_fw_element_hdr *elm,
+ const union rtw89_fw_element_arg arg)
+{
+ struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+
+ elm_info->diag_mac = elm;
+
+ return 0;
+}
+
static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
[RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
{ .fw_type = RTW89_FW_BBMCU0 }, NULL},
@@ -1386,6 +1398,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
[RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ] = {
rtw89_build_afe_pwr_seq_from_elm, {}, "AFE",
},
+ [RTW89_FW_ELEMENT_ID_DIAG_MAC] = {
+ rtw89_recognize_diag_mac_from_elm, {}, NULL,
+ },
};
int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index ddebf7972068..d184856f6c76 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -3985,6 +3985,7 @@ enum rtw89_fw_element_id {
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ = 25,
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26,
RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ = 27,
+ RTW89_FW_ELEMENT_ID_DIAG_MAC = 28,
RTW89_FW_ELEMENT_ID_NUM,
};
@@ -4162,6 +4163,11 @@ struct rtw89_fw_element_hdr {
__le32 val;
} __packed infos[];
} __packed afe;
+ struct {
+ __le32 rule_size;
+ u8 rsvd[4];
+ u8 rules_and_msgs[];
+ } __packed diag_mac;
struct __rtw89_fw_txpwr_element txpwr;
struct __rtw89_fw_regd_element regd;
} __packed u;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 3/8] wifi: rtw89: debug: add parser to diagnose along DIAG_MAC fw element
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
2025-11-04 9:14 ` [PATCH rtw-next 1/8] wifi: rtw89: pci: add to read PCI configuration space from common code pkshih
2025-11-04 9:14 ` [PATCH rtw-next 2/8] wifi: rtw89: fw: parse firmware element of DIAG_MAC pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 4/8] wifi: rtw89: 8852c: add compensation of thermal value from efuse calibration pkshih
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
The rules to diagnose MAC have a common header, and a cmd field is used
to know the exact command and its format. The rules with the same tuple of
fields {sheet, seq} can be seen as a set of compound rules, which treat
it as positive rule if just one of the rules is positive.
Take EQUALV rules as example, if value of {addr, mask} is equal to
predefined value as field val, a rule is positive. Fields addr_name_offset
and msg_offset are offsets related to textual messages for human readable.
Format of common rule header (8 bytes)
+-------+-----+--------+-----------+-----+---------+
| sheet | cmd | seq[2] | io / band | len | rsvd[2] |
+-------+-----+--------+-----------+-----+---------+
Format of rule command is EQUALV (equal value) (24 bytes):
+------+------------------+------+-----+------------+---------+
| addr | addr_name_offset | mask | val | msg_offset | rsvd[4] |
+------+------------------+------+-----+------------+---------+
Format of message:
+-----+----------+
| len | string[] |
+-----+----------+
An example of output:
Plain(Ignore)/Rules/Positive: 115(4)/86/81
Where, Plain is total rules written in firmware element.
Ignore is the ignored rules, such as USB IO, but current is PCIE.
Rules is number of set of compound rules.
Positive is number of positive Rules.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/debug.c | 299 +++++++++++++++++++++
1 file changed, 299 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 3dc7981c510f..1264c2f82600 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -87,6 +87,7 @@ struct rtw89_debugfs {
struct rtw89_debugfs_priv disable_dm;
struct rtw89_debugfs_priv mlo_mode;
struct rtw89_debugfs_priv beacon_info;
+ struct rtw89_debugfs_priv diag_mac;
};
struct rtw89_debugfs_iter_data {
@@ -4361,6 +4362,302 @@ rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev,
return count;
}
+enum __diag_mac_cmd {
+ __CMD_EQUALV,
+ __CMD_EQUALO,
+ __CMD_NEQUALV,
+ __CMD_NEQUALO,
+ __CMD_SETEQUALV,
+ __CMD_SETEQUALO,
+ __CMD_CMPWCR,
+ __CMD_CMPWWD,
+ __CMD_NEQ_CMPWCR,
+ __CMD_NEQ_CMPWWD,
+ __CMD_INCREMENT,
+ __CMD_MESSAGE,
+};
+
+enum __diag_mac_io {
+ __IO_NORMAL,
+ __IO_NORMAL_PCIE,
+ __IO_NORMAL_USB,
+ __IO_NORMAL_SDIO,
+ __IO_PCIE_CFG,
+ __IO_SDIO_CCCR,
+};
+
+struct __diag_mac_rule_header {
+ u8 sheet;
+ u8 cmd;
+ u8 seq_major;
+ u8 seq_minor;
+ u8 io_band;
+ #define __DIAG_MAC_IO GENMASK(3, 0)
+ #define __DIAG_MAC_N_BAND BIT(4)
+ #define __DIAG_MAC_HAS_BAND BIT(5)
+ u8 len; /* include header. Unit: 4 bytes */
+ u8 rsvd[2];
+} __packed;
+
+struct __diag_mac_rule_equal {
+ struct __diag_mac_rule_header header;
+ __le32 addr;
+ __le32 addr_name_offset;
+ __le32 mask;
+ __le32 val;
+ __le32 msg_offset;
+ u8 rsvd[4];
+} __packed;
+
+struct __diag_mac_rule_increment {
+ struct __diag_mac_rule_header header;
+ __le32 addr;
+ __le32 addr_name_offset;
+ __le32 mask;
+ __le16 sel;
+ __le16 delay;
+ __le32 msg_offset;
+ u8 rsvd[4];
+} __packed;
+
+struct __diag_mac_msg_buf {
+ __le16 len;
+ char string[];
+} __packed;
+
+static ssize_t rtw89_mac_diag_do_equalv(struct rtw89_dev *rtwdev,
+ char *buf, size_t bufsz,
+ const struct __diag_mac_rule_equal *r,
+ const void *msg_start,
+ u64 *positive_bmp)
+{
+ const struct __diag_mac_msg_buf *name = msg_start +
+ le32_to_cpu(r->addr_name_offset);
+ const struct __diag_mac_msg_buf *msg = msg_start +
+ le32_to_cpu(r->msg_offset);
+ bool want_eq = r->header.cmd == __CMD_EQUALV;
+ char *p = buf, *end = buf + bufsz;
+ bool equal = false;
+ u32 val;
+
+ *positive_bmp <<= 1;
+
+ if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
+ val = rtw89_read32_pci_cfg(rtwdev, le32_to_cpu(r->addr));
+ else
+ val = rtw89_read32(rtwdev, le32_to_cpu(r->addr));
+
+ if ((val & le32_to_cpu(r->mask)) == le32_to_cpu(r->val))
+ equal = true;
+
+ if (want_eq == equal) {
+ *positive_bmp |= BIT(0);
+ return p - buf;
+ }
+
+ p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s => %x, %.*s\n",
+ r->header.sheet, r->header.cmd, le16_to_cpu(name->len),
+ name->string, val, le16_to_cpu(msg->len), msg->string);
+
+ return p - buf;
+}
+
+static ssize_t rtw89_mac_diag_do_increment(struct rtw89_dev *rtwdev,
+ char *buf, size_t bufsz,
+ const struct __diag_mac_rule_increment *r,
+ const void *msg_start,
+ u64 *positive_bmp)
+{
+ const struct __diag_mac_msg_buf *name = msg_start +
+ le32_to_cpu(r->addr_name_offset);
+ const struct __diag_mac_msg_buf *msg = msg_start +
+ le32_to_cpu(r->msg_offset);
+ char *p = buf, *end = buf + bufsz;
+ u32 addr = le32_to_cpu(r->addr);
+ u32 mask = le32_to_cpu(r->mask);
+ u16 sel = le16_to_cpu(r->sel);
+ u32 val1, val2;
+
+ *positive_bmp <<= 1;
+
+ rtw89_write32(rtwdev, addr, sel);
+
+ if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
+ val1 = rtw89_read32_pci_cfg(rtwdev, addr);
+ else
+ val1 = rtw89_read32(rtwdev, addr);
+
+ mdelay(le16_to_cpu(r->delay));
+
+ if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG)
+ val2 = rtw89_read32_pci_cfg(rtwdev, addr);
+ else
+ val2 = rtw89_read32(rtwdev, addr);
+
+ if ((val2 & mask) > (val1 & mask)) {
+ *positive_bmp |= BIT(0);
+ return p - buf;
+ }
+
+ p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s [%d]=> %x, %.*s\n",
+ r->header.sheet, r->header.cmd, le16_to_cpu(name->len),
+ name->string, le16_to_cpu(r->sel), val1,
+ le16_to_cpu(msg->len), msg->string);
+
+ return p - buf;
+}
+
+static bool rtw89_mac_diag_match_hci(struct rtw89_dev *rtwdev,
+ const struct __diag_mac_rule_header *rh)
+{
+ switch (u8_get_bits(rh->io_band, __DIAG_MAC_IO)) {
+ case __IO_NORMAL:
+ default:
+ return true;
+ case __IO_NORMAL_PCIE:
+ case __IO_PCIE_CFG:
+ if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE)
+ return true;
+ break;
+ case __IO_NORMAL_USB:
+ if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+ return true;
+ break;
+ case __IO_NORMAL_SDIO:
+ case __IO_SDIO_CCCR:
+ if (rtwdev->hci.type == RTW89_HCI_TYPE_SDIO)
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+static bool rtw89_mac_diag_match_band(struct rtw89_dev *rtwdev,
+ const struct __diag_mac_rule_header *rh)
+{
+ u8 active_bands;
+ bool has_band;
+ u8 band;
+
+ has_band = u8_get_bits(rh->io_band, __DIAG_MAC_HAS_BAND);
+ if (!has_band)
+ return true;
+
+ band = u8_get_bits(rh->io_band, __DIAG_MAC_N_BAND);
+ active_bands = rtw89_get_active_phy_bitmap(rtwdev);
+
+ if (active_bands & BIT(band))
+ return true;
+
+ return false;
+}
+
+static ssize_t rtw89_mac_diag_iter_all(struct rtw89_dev *rtwdev,
+ char *buf, size_t bufsz)
+{
+ const struct rtw89_fw_element_hdr *elm = rtwdev->fw.elm_info.diag_mac;
+ u32 n_plains = 0, n_rules = 0, n_positive = 0, n_ignore = 0;
+ char *p = buf, *end = buf + bufsz, *p_rewind;
+ const void *rule, *rule_end;
+ u32 elm_size, rule_size;
+ const void *msg_start;
+ u64 positive_bmp = 0;
+ u8 prev_sheet = 0;
+ u8 prev_seq = 0;
+ int limit;
+
+ if (!elm) {
+ p += scnprintf(p, end - p, "No diag_mac entry\n");
+ goto out;
+ }
+
+ rule_size = le32_to_cpu(elm->u.diag_mac.rule_size);
+ elm_size = le32_to_cpu(elm->size);
+
+ if (ALIGN(rule_size, 16) > elm_size) {
+ p += scnprintf(p, end - p, "rule size (%u) exceed elm_size (%u)\n",
+ ALIGN(rule_size, 16), elm_size);
+ goto out;
+ }
+
+ rule = &elm->u.diag_mac.rules_and_msgs[0];
+ rule_end = &elm->u.diag_mac.rules_and_msgs[rule_size];
+ msg_start = &elm->u.diag_mac.rules_and_msgs[ALIGN(rule_size, 16)];
+
+ for (limit = 0; limit < 5000 && rule < rule_end; limit++) {
+ const struct __diag_mac_rule_header *rh = rule;
+ u8 sheet = rh->sheet;
+ u8 seq = rh->seq_major;
+
+ if (!rtw89_mac_diag_match_hci(rtwdev, rh) ||
+ !rtw89_mac_diag_match_band(rtwdev, rh)) {
+ n_ignore++;
+ goto next;
+ }
+
+ if (!seq || prev_sheet != sheet || prev_seq != seq) {
+ if (positive_bmp) {
+ n_positive++;
+ /*
+ * discard output for negative results if one in
+ * a sequence set is positive.
+ */
+ if (p_rewind)
+ p = p_rewind;
+ }
+ p_rewind = seq ? p : NULL;
+ positive_bmp = 0;
+ n_rules++;
+ }
+
+ switch (rh->cmd) {
+ case __CMD_EQUALV:
+ case __CMD_NEQUALV:
+ p += rtw89_mac_diag_do_equalv(rtwdev, p, end - p, rule,
+ msg_start, &positive_bmp);
+ break;
+ case __CMD_INCREMENT:
+ p += rtw89_mac_diag_do_increment(rtwdev, p, end - p, rule,
+ msg_start, &positive_bmp);
+ break;
+ default:
+ p += scnprintf(p, end - p, "unknown rule cmd %u\n", rh->cmd);
+ break;
+ }
+
+next:
+ n_plains++;
+ rule += rh->len * 4;
+ prev_seq = seq;
+ prev_sheet = sheet;
+ }
+
+ if (positive_bmp) {
+ n_positive++;
+ if (p_rewind)
+ p = p_rewind;
+ }
+
+ p += scnprintf(p, end - p, "\nPlain(Ignore)/Rules/Positive: %u(%u)/%u/%u\n",
+ n_plains, n_ignore, n_rules, n_positive);
+
+out:
+ return p - buf;
+}
+
+static ssize_t
+rtw89_debug_priv_diag_mac_get(struct rtw89_dev *rtwdev,
+ struct rtw89_debugfs_priv *debugfs_priv,
+ char *buf, size_t bufsz)
+{
+ lockdep_assert_wiphy(rtwdev->hw->wiphy);
+
+ rtw89_leave_lps(rtwdev);
+
+ return rtw89_mac_diag_iter_all(rtwdev, buf, bufsz);
+}
+
static ssize_t
rtw89_debug_priv_beacon_info_get(struct rtw89_dev *rtwdev,
struct rtw89_debugfs_priv *debugfs_priv,
@@ -4478,6 +4775,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = {
.disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK),
.mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK),
.beacon_info = rtw89_debug_priv_get(beacon_info),
+ .diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK),
};
#define rtw89_debugfs_add(name, mode, fopname, parent) \
@@ -4524,6 +4822,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top
rtw89_debugfs_add_rw(disable_dm);
rtw89_debugfs_add_rw(mlo_mode);
rtw89_debugfs_add_r(beacon_info);
+ rtw89_debugfs_add_r(diag_mac);
}
void rtw89_debugfs_init(struct rtw89_dev *rtwdev)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 4/8] wifi: rtw89: 8852c: add compensation of thermal value from efuse calibration
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
` (2 preceding siblings ...)
2025-11-04 9:14 ` [PATCH rtw-next 3/8] wifi: rtw89: debug: add parser to diagnose along DIAG_MAC fw element pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 5/8] wifi: rtw89: phy: fix out-of-bounds access in rtw89_phy_read_txpwr_limit() pkshih
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
The 3th bit of thermal value programmed in efuse means 8 (2 ^ 3) grams.
Check the bit and signed bit, and add compensation to final thermal.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/rtw8852c.c | 27 +++++++++++++++----
1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 8550ae3bcb64..6be56c2fa0c7 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -670,12 +670,16 @@ static void rtw8852c_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev,
}
}
+#define __THM_MASK_SIGN BIT(0)
+#define __THM_MASK_3BITS GENMASK(3, 1)
+#define __THM_MASK_VAL8 BIT(4)
+
static void rtw8852c_thermal_trim(struct rtw89_dev *rtwdev)
{
-#define __thm_setting(raw) \
-({ \
- u8 __v = (raw); \
- ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \
+#define __thm_setting(raw) \
+({ \
+ u8 __v = (raw); \
+ ((__v & __THM_MASK_SIGN) << 3) | ((__v & __THM_MASK_3BITS) >> 1); \
})
struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
u8 i, val;
@@ -2516,13 +2520,26 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ s8 comp = 0;
+ u8 val;
+
rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0);
rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
fsleep(200);
- return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL);
+ val = rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL);
+
+ if (info->pg_thermal_trim) {
+ u8 trim = info->thermal_trim[rf_path];
+
+ if (trim & __THM_MASK_VAL8)
+ comp = 8 * (trim & __THM_MASK_SIGN ? -1 : 1);
+ }
+
+ return val + comp;
}
static void rtw8852c_btc_set_rfe(struct rtw89_dev *rtwdev)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 5/8] wifi: rtw89: phy: fix out-of-bounds access in rtw89_phy_read_txpwr_limit()
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
` (3 preceding siblings ...)
2025-11-04 9:14 ` [PATCH rtw-next 4/8] wifi: rtw89: 8852c: add compensation of thermal value from efuse calibration pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 6/8] wifi: rtw89: consider data rate/bandwidth/GI for injected packets pkshih
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Kuan-Chung Chen <damon.chen@realtek.com>
Coverity reported a potential out-of-bounds access when 'bw' exceeds the
valid range for the specified band. Add a helper `rtw89_bw_is_valid()`
to check bandwidth validity for each band before accessing limit tables.
Addresses-Coverity-ID: 1598844 ("Out-of-bounds access")
Addresses-Coverity-ID: 1598896 ("Out-of-bounds access")
Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/phy.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 23892c1359a5..28e2b15240a7 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -2376,6 +2376,21 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
}
}
+static bool rtw89_phy_validate_txpwr_limit_bw(struct rtw89_dev *rtwdev,
+ u8 band, u8 bw)
+{
+ switch (band) {
+ case RTW89_BAND_2G:
+ return bw < RTW89_2G_BW_NUM;
+ case RTW89_BAND_5G:
+ return bw < RTW89_5G_BW_NUM;
+ case RTW89_BAND_6G:
+ return bw < RTW89_6G_BW_NUM;
+ default:
+ return false;
+ }
+}
+
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
{
@@ -2400,6 +2415,11 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
};
s8 cstr;
+ if (!rtw89_phy_validate_txpwr_limit_bw(rtwdev, band, bw)) {
+ rtw89_warn(rtwdev, "invalid band %u bandwidth %u\n", band, bw);
+ return 0;
+ }
+
switch (band) {
case RTW89_BAND_2G:
if (has_ant_gain)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 6/8] wifi: rtw89: consider data rate/bandwidth/GI for injected packets
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
` (4 preceding siblings ...)
2025-11-04 9:14 ` [PATCH rtw-next 5/8] wifi: rtw89: phy: fix out-of-bounds access in rtw89_phy_read_txpwr_limit() pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 7/8] wifi: rtw89: do RF calibration once setting channel when running pure monitor mode pkshih
2025-11-04 9:14 ` [PATCH rtw-next 8/8] wifi: rtw89: configure RX antenna if chips can support pkshih
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
To send injected packets with configurable rate/bandwidth/GI, fill TXWD
fields according to SKB's info->control.rates[0] annotated by mac80211.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.c | 67 +++++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/core.h | 2 +
2 files changed, 69 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 1f92be300ea7..9bb3c05bb738 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -321,6 +321,26 @@ static const struct ieee80211_supported_band rtw89_sband_6ghz = {
.n_bitrates = ARRAY_SIZE(rtw89_bitrates) - 4,
};
+static const struct rtw89_hw_rate_def {
+ enum rtw89_hw_rate ht;
+ enum rtw89_hw_rate vht[RTW89_NSS_NUM];
+} rtw89_hw_rate[RTW89_CHIP_GEN_NUM] = {
+ [RTW89_CHIP_AX] = {
+ .ht = RTW89_HW_RATE_MCS0,
+ .vht = {RTW89_HW_RATE_VHT_NSS1_MCS0,
+ RTW89_HW_RATE_VHT_NSS2_MCS0,
+ RTW89_HW_RATE_VHT_NSS3_MCS0,
+ RTW89_HW_RATE_VHT_NSS4_MCS0},
+ },
+ [RTW89_CHIP_BE] = {
+ .ht = RTW89_HW_RATE_V1_MCS0,
+ .vht = {RTW89_HW_RATE_V1_VHT_NSS1_MCS0,
+ RTW89_HW_RATE_V1_VHT_NSS2_MCS0,
+ RTW89_HW_RATE_V1_VHT_NSS3_MCS0,
+ RTW89_HW_RATE_V1_VHT_NSS4_MCS0},
+ },
+};
+
static void __rtw89_traffic_stats_accu(struct rtw89_traffic_stats *stats,
struct sk_buff *skb, bool tx)
{
@@ -1097,6 +1117,44 @@ rtw89_core_tx_wake(struct rtw89_dev *rtwdev,
rtw89_mac_notify_wake(rtwdev);
}
+static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev,
+ struct rtw89_core_tx_request *tx_req,
+ struct ieee80211_tx_info *info)
+{
+ const struct rtw89_hw_rate_def *hw_rate = &rtw89_hw_rate[rtwdev->chip->chip_gen];
+ enum mac80211_rate_control_flags flags = info->control.rates[0].flags;
+ struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+ const struct rtw89_chan *chan;
+ u8 idx = info->control.rates[0].idx;
+ u8 nss, mcs;
+
+ desc_info->use_rate = true;
+ desc_info->dis_data_fb = true;
+
+ if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ desc_info->data_bw = 3;
+ else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ desc_info->data_bw = 2;
+ else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ desc_info->data_bw = 1;
+
+ if (flags & IEEE80211_TX_RC_SHORT_GI)
+ desc_info->gi_ltf = 1;
+
+ if (flags & IEEE80211_TX_RC_VHT_MCS) {
+ nss = umin(idx >> 4, ARRAY_SIZE(hw_rate->vht) - 1);
+ mcs = idx & 0xf;
+ desc_info->data_rate = hw_rate->vht[nss] + mcs;
+ } else if (flags & IEEE80211_TX_RC_MCS) {
+ desc_info->data_rate = hw_rate->ht + idx;
+ } else {
+ chan = rtw89_chan_get(rtwdev, tx_req->rtwvif_link->chanctx_idx);
+
+ desc_info->data_rate = idx + (chan->band_type == RTW89_BAND_2G ?
+ RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6);
+ }
+}
+
static void
rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
@@ -1152,6 +1210,9 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
rtw89_core_tx_update_h2c_info(rtwdev, tx_req);
break;
}
+
+ if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
+ rtw89_core_tx_update_injection(rtwdev, tx_req, info);
}
static void rtw89_tx_wait_work(struct wiphy *wiphy, struct wiphy_work *work)
@@ -1381,6 +1442,8 @@ static __le32 rtw89_build_txwd_body5(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(RTW89_TXWD_BODY7_USE_RATE_V1, desc_info->use_rate) |
+ FIELD_PREP(RTW89_TXWD_BODY7_DATA_BW, desc_info->data_bw) |
+ FIELD_PREP(RTW89_TXWD_BODY7_GI_LTF, desc_info->gi_ltf) |
FIELD_PREP(RTW89_TXWD_BODY7_DATA_RATE, desc_info->data_rate);
return cpu_to_le32(dword);
@@ -1389,6 +1452,8 @@ static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) |
+ FIELD_PREP(RTW89_TXWD_INFO0_DATA_BW, desc_info->data_bw) |
+ FIELD_PREP(RTW89_TXWD_INFO0_GI_LTF, desc_info->gi_ltf) |
FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) |
FIELD_PREP(RTW89_TXWD_INFO0_DATA_STBC, desc_info->stbc) |
FIELD_PREP(RTW89_TXWD_INFO0_DATA_LDPC, desc_info->ldpc) |
@@ -1568,6 +1633,8 @@ static __le32 rtw89_build_txwd_body6_v2(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_body7_v2(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(BE_TXD_BODY7_USERATE_SEL, desc_info->use_rate) |
+ FIELD_PREP(BE_TXD_BODY7_DATA_BW, desc_info->data_bw) |
+ FIELD_PREP(BE_TXD_BODY7_GI_LTF, desc_info->gi_ltf) |
FIELD_PREP(BE_TXD_BODY7_DATA_ER, desc_info->er_cap) |
FIELD_PREP(BE_TXD_BODY7_DATA_BW_ER, 0) |
FIELD_PREP(BE_TXD_BODY7_DATARATE, desc_info->data_rate);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 01bfc5b473f5..02d9d42cdbb5 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -1178,6 +1178,8 @@ struct rtw89_tx_desc_info {
u8 sec_seq[6];
u16 data_rate;
u16 data_retry_lowest_rate;
+ u8 data_bw;
+ u8 gi_ltf;
bool fw_dl;
u16 seq;
bool a_ctrl_bsr;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 7/8] wifi: rtw89: do RF calibration once setting channel when running pure monitor mode
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
` (5 preceding siblings ...)
2025-11-04 9:14 ` [PATCH rtw-next 6/8] wifi: rtw89: consider data rate/bandwidth/GI for injected packets pkshih
@ 2025-11-04 9:14 ` pkshih
2025-11-04 9:14 ` [PATCH rtw-next 8/8] wifi: rtw89: configure RX antenna if chips can support pkshih
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
To be able to capture and inject packets in monitor mode, do RF calibration
once setting certain channel. Since calibration costs time, do not change
behavior of normal usage, which do calibration only when starting as AP
or going to connect AP.
Since driver declares IEEE80211_HW_WANT_MONITOR_VIF, the pure monitor vif
must be only one when adding interface with type NL80211_IFTYPE_MONITOR.
Otherwise, monitor vif must be NULL.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.c | 18 ++++++++++++++++++
drivers/net/wireless/realtek/rtw89/core.h | 1 +
drivers/net/wireless/realtek/rtw89/mac80211.c | 4 ++++
3 files changed, 23 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 9bb3c05bb738..9cc0e681ef47 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -470,6 +470,22 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
__rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1);
}
+static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_vif *rtwvif = rtwdev->pure_monitor_mode_vif;
+ struct rtw89_vif_link *rtwvif_link;
+
+ if (!rtwvif)
+ return;
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, phy_idx);
+ if (!rtwvif_link)
+ return;
+
+ rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
+}
+
static void __rtw89_set_channel(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_mac_idx mac_idx,
@@ -498,6 +514,8 @@ static void __rtw89_set_channel(struct rtw89_dev *rtwdev,
}
rtw89_set_entity_state(rtwdev, phy_idx, true);
+
+ rtw89_chip_rfk_channel_for_pure_mon_vif(rtwdev, phy_idx);
}
int rtw89_set_channel(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 02d9d42cdbb5..e6a45e1e7b7c 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -6102,6 +6102,7 @@ struct rtw89_dev {
int napi_budget_countdown;
struct rtw89_debugfs *debugfs;
+ struct rtw89_vif *pure_monitor_mode_vif;
/* HCI related data, keep last */
u8 priv[] __aligned(sizeof(void *));
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index a19304ff8306..14c8864bd201 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -220,6 +220,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
if (ret)
goto unset_link;
+ rtwdev->pure_monitor_mode_vif = vif->type == NL80211_IFTYPE_MONITOR ?
+ rtwvif : NULL;
rtw89_recalc_lps(rtwdev);
return 0;
@@ -267,6 +269,8 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
rtw89_core_release_bit_map(rtwdev->hw_port, port);
rtw89_release_mac_id(rtwdev, macid);
+ rtwdev->pure_monitor_mode_vif = NULL;
+
rtw89_recalc_lps(rtwdev);
rtw89_enter_ips_by_hwflags(rtwdev);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH rtw-next 8/8] wifi: rtw89: configure RX antenna if chips can support
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
` (6 preceding siblings ...)
2025-11-04 9:14 ` [PATCH rtw-next 7/8] wifi: rtw89: do RF calibration once setting channel when running pure monitor mode pkshih
@ 2025-11-04 9:14 ` pkshih
7 siblings, 0 replies; 9+ messages in thread
From: pkshih @ 2025-11-04 9:14 UTC (permalink / raw)
To: linux-wireless; +Cc: damon.chen
From: Ping-Ke Shih <pkshih@realtek.com>
If chip->ops->cfg_txrx_path is implemented, a chip can support to configure
RX antenna, so accept setting via iw tool.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/mac80211.c | 5 +++++
.../net/wireless/realtek/rtw89/rtw8852b_common.c | 6 +++++-
drivers/net/wireless/realtek/rtw89/rtw8852c.c | 14 ++++++++++++--
drivers/net/wireless/realtek/rtw89/rtw8922a.c | 12 +++++++++++-
4 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 14c8864bd201..6f7571c7c274 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -1147,12 +1147,17 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, u3
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_hal *hal = &rtwdev->hal;
+ const struct rtw89_chip_info *chip;
lockdep_assert_wiphy(hw->wiphy);
+ chip = rtwdev->chip;
+
if (hal->ant_diversity) {
if (tx_ant != rx_ant || hweight32(tx_ant) != 1)
return -EINVAL;
+ } else if (chip->ops->cfg_txrx_path) {
+ /* With cfg_txrx_path ops, chips can configure rx_ant */
} else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) {
return -EINVAL;
}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
index 3fb2972ae6f6..4e72f4961837 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
@@ -1747,11 +1747,15 @@ static void __rtw8852bx_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
enum rtw89_rf_path_bit rx_path = hal->antenna_rx ? hal->antenna_rx : RF_AB;
+ u8 rx_nss = rtwdev->hal.rx_nss;
+
+ if (rx_path != RF_AB)
+ rx_nss = 1;
rtw8852bx_bb_ctrl_rx_path(rtwdev, rx_path, chan);
rtw8852bx_bb_ctrl_rf_mode_rx_path(rtwdev, rx_path);
- if (rtwdev->hal.rx_nss == 1) {
+ if (rx_nss == 1) {
rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 6be56c2fa0c7..ee81a6792eee 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2502,10 +2502,20 @@ static void rtw8852c_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 nrx_path = RF_PATH_AB;
+ u8 rx_nss = hal->rx_nss;
- rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB);
+ if (hal->antenna_rx == RF_A)
+ nrx_path = RF_PATH_A;
+ else if (hal->antenna_rx == RF_B)
+ nrx_path = RF_PATH_B;
- if (hal->rx_nss == 1) {
+ if (nrx_path != RF_PATH_AB)
+ rx_nss = 1;
+
+ rtw8852c_bb_cfg_rx_path(rtwdev, nrx_path);
+
+ if (rx_nss == 1) {
rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 61f3a0a3f440..11e8b50a3291 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2347,19 +2347,29 @@ static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
enum rtw89_band band = chan->band_type;
struct rtw89_hal *hal = &rtwdev->hal;
u8 ntx_path = RF_PATH_AB;
+ u8 nrx_path = RF_PATH_AB;
u32 tx_en0, tx_en1;
+ u8 rx_nss = 2;
if (hal->antenna_tx == RF_A)
ntx_path = RF_PATH_A;
else if (hal->antenna_tx == RF_B)
ntx_path = RF_PATH_B;
+ if (hal->antenna_rx == RF_A)
+ nrx_path = RF_PATH_A;
+ else if (hal->antenna_rx == RF_B)
+ nrx_path = RF_PATH_B;
+
+ if (nrx_path != RF_PATH_AB)
+ rx_nss = 1;
+
rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, true);
if (rtwdev->dbcc_en)
rtw8922a_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band,
&tx_en1, true);
- rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, RF_PATH_AB, 2);
+ rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, nrx_path, rx_nss);
rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false);
if (rtwdev->dbcc_en)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-11-04 9:11 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-04 9:14 [PATCH rtw-next 0/8] wifi: rtw89: update rate/bw/GI for injection, and add diagnosis to debugfs pkshih
2025-11-04 9:14 ` [PATCH rtw-next 1/8] wifi: rtw89: pci: add to read PCI configuration space from common code pkshih
2025-11-04 9:14 ` [PATCH rtw-next 2/8] wifi: rtw89: fw: parse firmware element of DIAG_MAC pkshih
2025-11-04 9:14 ` [PATCH rtw-next 3/8] wifi: rtw89: debug: add parser to diagnose along DIAG_MAC fw element pkshih
2025-11-04 9:14 ` [PATCH rtw-next 4/8] wifi: rtw89: 8852c: add compensation of thermal value from efuse calibration pkshih
2025-11-04 9:14 ` [PATCH rtw-next 5/8] wifi: rtw89: phy: fix out-of-bounds access in rtw89_phy_read_txpwr_limit() pkshih
2025-11-04 9:14 ` [PATCH rtw-next 6/8] wifi: rtw89: consider data rate/bandwidth/GI for injected packets pkshih
2025-11-04 9:14 ` [PATCH rtw-next 7/8] wifi: rtw89: do RF calibration once setting channel when running pure monitor mode pkshih
2025-11-04 9:14 ` [PATCH rtw-next 8/8] wifi: rtw89: configure RX antenna if chips can support pkshih
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).