mac80211: rt2x00: some improvements for rt2800 generic

1. Respect the rt2800 hardware TX queue index.
2. Increase the watchdog sampling frequency.

Signed-off-by: Shiji Yang <yangshiji66@qq.com>
Link: https://github.com/openwrt/openwrt/pull/16845
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Shiji Yang 2024-12-25 19:39:29 +08:00 committed by Hauke Mehrtens
parent c9ae39b2d1
commit 70733c6093
4 changed files with 344 additions and 13 deletions

View File

@ -0,0 +1,257 @@
From 654653e718f6c55c6f29fd94cc8152a92c8166ac Mon Sep 17 00:00:00 2001
From: Shiji Yang <yangshiji66@outlook.com>
Date: Tue, 24 Dec 2024 08:36:32 +0800
Subject: [PATCH 1/2] rt2x00: respect the rt2800 hardware TX queue index
The Ralink TX queue register index is different from the Linux
IEEE80211 queue id definition. Their conversion table is as follows:
Queue IEEE80211 Ralink
AC_VO 0 3
AC_VI 1 2
AC_BE 2 0
AC_BK 3 1
The TX queues are still functioning properly under the current
configuration. I don't have evidence, but I believe there should
be some differences in the internal hardware implementation of
different TX queues, e.g. interrupt priority. so it's better to
respect the queue index defined by the Ralink when we construct
the TX rings and descriptors.
And the more important thing is that we are using the wrong queue
index to calculate the register offset and mask in .conf_tx(),
which resulted in writing incorrect AIFSN, CWMAX, CWMIN and TXOP
values for all TX queues. This patch introduces a index conversion
table to fix these parameters.
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800.h | 24 ++++++------
.../net/wireless/ralink/rt2x00/rt2800lib.c | 20 +++++++---
.../net/wireless/ralink/rt2x00/rt2800mmio.c | 38 ++++++++++---------
.../net/wireless/ralink/rt2x00/rt2x00queue.h | 20 ++++++++++
4 files changed, 67 insertions(+), 35 deletions(-)
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -379,10 +379,10 @@
/*
* WMM_AIFSN_CFG: Aifsn for each EDCA AC
- * AIFSN0: AC_VO
- * AIFSN1: AC_VI
- * AIFSN2: AC_BE
- * AIFSN3: AC_BK
+ * AIFSN0: AC_BE
+ * AIFSN1: AC_BK
+ * AIFSN2: AC_VI
+ * AIFSN3: AC_VO
*/
#define WMM_AIFSN_CFG 0x0214
#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f)
@@ -392,10 +392,10 @@
/*
* WMM_CWMIN_CSR: CWmin for each EDCA AC
- * CWMIN0: AC_VO
- * CWMIN1: AC_VI
- * CWMIN2: AC_BE
- * CWMIN3: AC_BK
+ * CWMIN0: AC_BE
+ * CWMIN1: AC_BK
+ * CWMIN2: AC_VI
+ * CWMIN3: AC_VO
*/
#define WMM_CWMIN_CFG 0x0218
#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f)
@@ -405,10 +405,10 @@
/*
* WMM_CWMAX_CSR: CWmax for each EDCA AC
- * CWMAX0: AC_VO
- * CWMAX1: AC_VI
- * CWMAX2: AC_BE
- * CWMAX3: AC_BK
+ * CWMAX0: AC_BE
+ * CWMAX1: AC_BK
+ * CWMAX2: AC_VI
+ * CWMAX3: AC_VO
*/
#define WMM_CWMAX_CFG 0x021c
#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f)
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -835,7 +835,8 @@ void rt2800_write_tx_data(struct queue_e
txdesc->key_idx : txdesc->u.ht.wcid);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
+ rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE,
+ rt2x00_ac_to_hwq(entry->queue->qid));
rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
rt2x00_desc_write(txwi, 1, word);
@@ -1125,6 +1126,12 @@ void rt2800_txdone(struct rt2x00_dev *rt
u32 reg;
u8 qid;
bool match;
+ static const u8 rt2ac[] = {
+ IEEE80211_AC_BE,
+ IEEE80211_AC_BK,
+ IEEE80211_AC_VI,
+ IEEE80211_AC_VO,
+ };
while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
/*
@@ -1132,6 +1139,8 @@ void rt2800_txdone(struct rt2x00_dev *rt
* guaranteed to be one of the TX QIDs .
*/
qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ /* Convert Ralink hardware queue index to IEEE80211 queue id. */
+ qid = rt2ac[qid];
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(rt2x00queue_empty(queue))) {
@@ -12188,8 +12197,9 @@ int rt2800_conf_tx(struct ieee80211_hw *
queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
/* Update WMM TXOP register */
- offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
- field.bit_offset = (queue_idx & 1) * 16;
+ offset = WMM_TXOP0_CFG +
+ (sizeof(u32) * (!!(rt2x00_ac_to_hwq(queue_idx) & 2)));
+ field.bit_offset = (rt2x00_ac_to_hwq(queue_idx) & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
reg = rt2800_register_read(rt2x00dev, offset);
@@ -12197,7 +12207,7 @@ int rt2800_conf_tx(struct ieee80211_hw *
rt2800_register_write(rt2x00dev, offset, reg);
/* Update WMM registers */
- field.bit_offset = queue_idx * 4;
+ field.bit_offset = rt2x00_ac_to_hwq(queue_idx) * 4;
field.bit_mask = 0xf << field.bit_offset;
reg = rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG);
@@ -12213,7 +12223,7 @@ int rt2800_conf_tx(struct ieee80211_hw *
rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
/* Update EDCA registers */
- offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
+ offset = EDCA_AC0_CFG + (sizeof(u32) * rt2x00_ac_to_hwq(queue_idx));
reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -35,7 +35,7 @@ unsigned int rt2800mmio_get_dma_done(str
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
- qid = queue->qid;
+ qid = rt2x00_ac_to_hwq(queue->qid);
idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid));
break;
case QID_MGMT:
@@ -456,6 +456,7 @@ void rt2800mmio_kick_queue(struct data_q
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry *entry;
+ u8 qid;
switch (queue->qid) {
case QID_AC_VO:
@@ -464,7 +465,8 @@ void rt2800mmio_kick_queue(struct data_q
case QID_AC_BK:
WARN_ON_ONCE(rt2x00queue_empty(queue));
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+ qid = rt2x00_ac_to_hwq(queue->qid);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(qid),
entry->entry_idx);
hrtimer_start(&rt2x00dev->txstatus_timer,
TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
@@ -666,36 +668,36 @@ int rt2800mmio_init_queues(struct rt2x00
* Initialize registers.
*/
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
entry_priv->desc_dma);
- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
rt2x00dev->tx[0].limit);
- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
entry_priv->desc_dma);
- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
rt2x00dev->tx[1].limit);
- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
entry_priv->desc_dma);
- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
rt2x00dev->tx[2].limit);
- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
entry_priv->desc_dma);
- rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
rt2x00dev->tx[3].limit);
- rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
- rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0);
rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0);
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
@@ -57,6 +57,26 @@ enum data_queue_qid {
};
/**
+ * rt2x00_ac_to_hwq - Convert IEEE80211 queue id to Ralink hardware
+ * queue register index.
+ * @ac: TX queue id.
+ */
+static inline u8 rt2x00_ac_to_hwq(enum data_queue_qid ac)
+{
+ static const u8 ralink_queue_map[] = {
+ [IEEE80211_AC_BE] = 0,
+ [IEEE80211_AC_BK] = 1,
+ [IEEE80211_AC_VI] = 2,
+ [IEEE80211_AC_VO] = 3,
+ };
+
+ if (unlikely(ac >= IEEE80211_NUM_ACS))
+ return ac;
+
+ return ralink_queue_map[ac];
+}
+
+/**
* enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
*
* @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX

View File

@ -0,0 +1,74 @@
From aec50d1a30349759de0ac535f54c3441bf7ebef7 Mon Sep 17 00:00:00 2001
From: Shiji Yang <yangshiji66@outlook.com>
Date: Sun, 22 Dec 2024 17:06:59 +0800
Subject: [PATCH 2/2] rt2x00: increase the watchdog sampling frequency
Increase the sampling frequency of the watchdog when the hung
counter reaches the threshold to avoid some unnecessary resets.
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
---
.../net/wireless/ralink/rt2x00/rt2800lib.c | 45 +++++++++++++------
1 file changed, 32 insertions(+), 13 deletions(-)
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1320,26 +1320,45 @@ static bool rt2800_watchdog_hung(struct
return true;
}
+static inline bool check_dma_busy_rx(u32 reg_cfg, u32 reg_int)
+{
+ return (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_RX_DMA_BUSY) &&
+ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_RX_COHERENT));
+}
+
+static inline bool check_dma_busy_tx(u32 reg_cfg, u32 reg_int)
+{
+ return (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
+ rt2x00_get_field32(reg_int, INT_SOURCE_CSR_TX_COHERENT));
+}
+
static bool rt2800_watchdog_dma_busy(struct rt2x00_dev *rt2x00dev)
{
bool busy_rx, busy_tx;
u32 reg_cfg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
u32 reg_int = rt2800_register_read(rt2x00dev, INT_SOURCE_CSR);
- if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_RX_DMA_BUSY) &&
- rt2x00_get_field32(reg_int, INT_SOURCE_CSR_RX_COHERENT))
- rt2x00dev->rxdma_busy++;
- else
- rt2x00dev->rxdma_busy = 0;
-
- if (rt2x00_get_field32(reg_cfg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
- rt2x00_get_field32(reg_int, INT_SOURCE_CSR_TX_COHERENT))
- rt2x00dev->txdma_busy++;
- else
- rt2x00dev->txdma_busy = 0;
+ rt2x00dev->rxdma_busy = check_dma_busy_rx(reg_cfg, reg_int) ?
+ rt2x00dev->rxdma_busy + 1 : 0;
+ rt2x00dev->txdma_busy = check_dma_busy_tx(reg_cfg, reg_int) ?
+ rt2x00dev->txdma_busy + 1 : 0;
+
+ if (rt2x00dev->rxdma_busy > 25 || rt2x00dev->txdma_busy > 25) {
+ int cnt;
+ for (cnt = 0; cnt < 10; cnt++) {
+ msleep(5);
+ reg_cfg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
+ reg_int = rt2800_register_read(rt2x00dev, INT_SOURCE_CSR);
+
+ if (!check_dma_busy_rx(reg_cfg, reg_int))
+ rt2x00dev->rxdma_busy = 0;
+ if (!check_dma_busy_tx(reg_cfg, reg_int))
+ rt2x00dev->txdma_busy = 0;
+ }
+ }
- busy_rx = rt2x00dev->rxdma_busy > 30;
- busy_tx = rt2x00dev->txdma_busy > 30;
+ busy_rx = rt2x00dev->rxdma_busy > 40;
+ busy_tx = rt2x00dev->txdma_busy > 40;
if (!busy_rx && !busy_tx)
return false;

View File

@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
[EEPROM_CHIP_ID] = 0x0000,
[EEPROM_VERSION] = 0x0001,
@@ -10404,8 +10422,10 @@ static void rt2800_calibration_rt6352(st
@@ -10432,8 +10450,10 @@ static void rt2800_calibration_rt6352(st
u32 reg;
if (rt2x00_has_cap_external_pa(rt2x00dev) ||
@ -64,7 +64,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
rt2800_r_calibration(rt2x00dev);
rt2800_rf_self_txdc_cal(rt2x00dev);
@@ -10423,6 +10443,8 @@ static void rt2800_calibration_rt6352(st
@@ -10451,6 +10471,8 @@ static void rt2800_calibration_rt6352(st
!rt2x00_has_cap_external_lna_bg(rt2x00dev))
return;

View File

@ -14,7 +14,7 @@
*/
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -3836,14 +3836,16 @@ static void rt2800_config_channel_rf7620
@@ -3864,14 +3864,16 @@ static void rt2800_config_channel_rf7620
rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4);
rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
@ -39,7 +39,7 @@
rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620,
@@ -3877,18 +3879,23 @@ static void rt2800_config_channel_rf7620
@@ -3905,18 +3907,23 @@ static void rt2800_config_channel_rf7620
rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20);
}
@ -73,7 +73,7 @@
if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) {
if (conf_is_ht40(conf)) {
@@ -4002,25 +4009,29 @@ static void rt2800_config_alc_rt6352(str
@@ -4030,25 +4037,29 @@ static void rt2800_config_alc_rt6352(str
if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n");
@ -121,7 +121,7 @@
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl);
rt2800_vco_calibration(rt2x00dev);
@@ -4513,7 +4524,8 @@ static void rt2800_config_channel(struct
@@ -4541,7 +4552,8 @@ static void rt2800_config_channel(struct
if (rt2x00_rt(rt2x00dev, RT6352)) {
/* BBP for GLRT BW */
bbp = conf_is_ht40(conf) ?
@ -131,7 +131,7 @@
0x15 : 0x1a;
rt2800_bbp_glrt_write(rt2x00dev, 141, bbp);
@@ -6017,18 +6029,33 @@ static int rt2800_init_registers(struct
@@ -6045,18 +6057,33 @@ static int rt2800_init_registers(struct
} else if (rt2x00_rt(rt2x00dev, RT5350)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
} else if (rt2x00_rt(rt2x00dev, RT6352)) {
@ -177,7 +177,7 @@
reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
rt2x00_set_field32(&reg, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
@@ -7141,14 +7168,16 @@ static void rt2800_init_bbp_6352(struct
@@ -7169,14 +7196,16 @@ static void rt2800_init_bbp_6352(struct
rt2800_bbp_write(rt2x00dev, 188, 0x00);
rt2800_bbp_write(rt2x00dev, 189, 0x00);
@ -202,7 +202,7 @@
/* BBP for G band GLRT function (BBP_128 ~ BBP_221) */
rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00);
@@ -10378,6 +10407,9 @@ static void rt2800_restore_rf_bbp_rt6352
@@ -10406,6 +10435,9 @@ static void rt2800_restore_rf_bbp_rt6352
rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0);
}
@ -212,7 +212,7 @@
if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
@@ -10455,6 +10487,9 @@ static void rt2800_calibration_rt6352(st
@@ -10483,6 +10515,9 @@ static void rt2800_calibration_rt6352(st
rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
}
@ -222,7 +222,7 @@
if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
@@ -10545,31 +10580,36 @@ static void rt2800_init_rfcsr_6352(struc
@@ -10573,31 +10608,36 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write(rt2x00dev, 42, 0x5B);
rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
@ -284,7 +284,7 @@
/* Initialize RF channel register to default value */
rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03);
@@ -10635,63 +10675,71 @@ static void rt2800_init_rfcsr_6352(struc
@@ -10663,63 +10703,71 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5);
@ -411,7 +411,7 @@
/* Initialize RF DC calibration register to default value */
rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47);
@@ -10754,12 +10802,17 @@ static void rt2800_init_rfcsr_6352(struc
@@ -10782,12 +10830,17 @@ static void rt2800_init_rfcsr_6352(struc
rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00);