Merge pull request #9623 from heitbaum/rtw

linux: wifi: rtw88: update patches as they have now been accepted into rtw-next
This commit is contained in:
Christian Hewitt 2024-12-29 00:50:27 +04:00 committed by GitHub
commit 315c07813d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 775 additions and 0 deletions

View File

@ -0,0 +1,209 @@
From 0daa521a1c8c29ffbefe6530f0d276e74e2749d0 Mon Sep 17 00:00:00 2001
From: Ping-Ke Shih <pkshih@realtek.com>
Date: Thu, 12 Dec 2024 13:42:03 +0800
Subject: [PATCH 29/35] wifi: rtw88: add __packed attribute to efuse layout
struct
The layout struct of efuse should not do address alignment by compiler.
Otherwise it leads unexpected layout and size for certain arch suc as arm.
In x86-64, the results are identical before and after this patch.
Also adjust bit-field to prevent over adjacent byte to avoid warning:
rtw88/rtw8822b.h:66:1: note: offset of packed bit-field `res2` has changed in GCC 4.4
66 | } __packed;
| ^
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202412120131.qk0x6OhE-lkp@intel.com/
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20241212054203.135046-1-pkshih@realtek.com
---
drivers/net/wireless/realtek/rtw88/main.h | 4 ++--
drivers/net/wireless/realtek/rtw88/rtw8723x.h | 8 ++++----
drivers/net/wireless/realtek/rtw88/rtw8821c.h | 9 +++++----
drivers/net/wireless/realtek/rtw88/rtw8822b.h | 9 +++++----
drivers/net/wireless/realtek/rtw88/rtw8822c.h | 9 +++++----
5 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index cd09fb6f7b8b..65c7acea41af 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -510,12 +510,12 @@ struct rtw_5g_txpwr_idx {
struct rtw_5g_vht_ns_pwr_idx_diff vht_2s_diff;
struct rtw_5g_vht_ns_pwr_idx_diff vht_3s_diff;
struct rtw_5g_vht_ns_pwr_idx_diff vht_4s_diff;
-};
+} __packed;
struct rtw_txpwr_idx {
struct rtw_2g_txpwr_idx pwr_idx_2g;
struct rtw_5g_txpwr_idx pwr_idx_5g;
-};
+} __packed;
struct rtw_channel_params {
u8 center_chan;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723x.h b/drivers/net/wireless/realtek/rtw88/rtw8723x.h
index e93bfce994bf..a99af527c92c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723x.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723x.h
@@ -47,7 +47,7 @@ struct rtw8723xe_efuse {
u8 device_id[2];
u8 sub_vendor_id[2];
u8 sub_device_id[2];
-};
+} __packed;
struct rtw8723xu_efuse {
u8 res4[48]; /* 0xd0 */
@@ -56,12 +56,12 @@ struct rtw8723xu_efuse {
u8 usb_option; /* 0x104 */
u8 res5[2]; /* 0x105 */
u8 mac_addr[ETH_ALEN]; /* 0x107 */
-};
+} __packed;
struct rtw8723xs_efuse {
u8 res4[0x4a]; /* 0xd0 */
u8 mac_addr[ETH_ALEN]; /* 0x11a */
-};
+} __packed;
struct rtw8723x_efuse {
__le16 rtl_id;
@@ -96,7 +96,7 @@ struct rtw8723x_efuse {
struct rtw8723xu_efuse u;
struct rtw8723xs_efuse s;
};
-};
+} __packed;
#define RTW8723X_IQK_ADDA_REG_NUM 16
#define RTW8723X_IQK_MAC8_REG_NUM 3
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index 7a33ebd612ed..954e93c8020d 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -27,7 +27,7 @@ struct rtw8821cu_efuse {
u8 res11[0xcf];
u8 package_type; /* 0x1fb */
u8 res12[0x4];
-};
+} __packed;
struct rtw8821ce_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
@@ -47,7 +47,8 @@ struct rtw8821ce_efuse {
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
- u8 res2:3;
+ u8 res2_1:1;
+ u8 res2_2:2;
u8 obff_cap:2;
u8 res3:4;
u8 res4[3];
@@ -63,7 +64,7 @@ struct rtw8821ce_efuse {
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
-};
+} __packed;
struct rtw8821cs_efuse {
u8 res4[0x4a]; /* 0xd0 */
@@ -101,7 +102,7 @@ struct rtw8821c_efuse {
struct rtw8821cu_efuse u;
struct rtw8821cs_efuse s;
};
-};
+} __packed;
static inline void
_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
index 0514958fb57c..9fca9ba67c90 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
@@ -27,7 +27,7 @@ struct rtw8822bu_efuse {
u8 res11[0xcf];
u8 package_type; /* 0x1fb */
u8 res12[0x4];
-};
+} __packed;
struct rtw8822be_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
@@ -47,7 +47,8 @@ struct rtw8822be_efuse {
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
- u8 res2:3;
+ u8 res2_1:1;
+ u8 res2_2:2;
u8 obff_cap:2;
u8 res3:4;
u8 res4[3];
@@ -63,7 +64,7 @@ struct rtw8822be_efuse {
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
-};
+} __packed;
struct rtw8822bs_efuse {
u8 res4[0x4a]; /* 0xd0 */
@@ -103,7 +104,7 @@ struct rtw8822b_efuse {
struct rtw8822bu_efuse u;
struct rtw8822bs_efuse s;
};
-};
+} __packed;
static inline void
_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
index e2b383d633cd..fc62b67a15f2 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -14,7 +14,7 @@ struct rtw8822cu_efuse {
u8 res1[3];
u8 mac_addr[ETH_ALEN]; /* 0x157 */
u8 res2[0x3d];
-};
+} __packed;
struct rtw8822cs_efuse {
u8 res0[0x4a]; /* 0x120 */
@@ -39,7 +39,8 @@ struct rtw8822ce_efuse {
u8 ltr_en:1;
u8 res1:2;
u8 obff:2;
- u8 res2:3;
+ u8 res2_1:1;
+ u8 res2_2:2;
u8 obff_cap:2;
u8 res3:4;
u8 class_code[3];
@@ -55,7 +56,7 @@ struct rtw8822ce_efuse {
u8 res6:1;
u8 port_t_power_on_value:5;
u8 res7;
-};
+} __packed;
struct rtw8822c_efuse {
__le16 rtl_id;
@@ -102,7 +103,7 @@ struct rtw8822c_efuse {
struct rtw8822cu_efuse u;
struct rtw8822cs_efuse s;
};
-};
+} __packed;
enum rtw8822c_dpk_agc_phase {
RTW_DPK_GAIN_CHECK,
--
2.43.0

View File

@ -0,0 +1,59 @@
From 66ef0289ac99e155d206ddaa0fdfad09ae3cd007 Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Wed, 18 Dec 2024 00:53:11 +0200
Subject: [PATCH 30/35] wifi: rtlwifi: rtl8821ae: Fix media status report
RTL8821AE is stuck transmitting at the lowest rate allowed by the rate
mask. This is because the firmware doesn't know the device is connected
to a network.
Fix the macros SET_H2CCMD_MSRRPT_PARM_OPMODE and
SET_H2CCMD_MSRRPT_PARM_MACID_IND to work on the first byte of __cmd,
not the second. Now the firmware is correctly notified when the device
is connected to a network and it activates the rate control.
Before (MCS3):
[ 5] 0.00-1.00 sec 12.5 MBytes 105 Mbits/sec 0 339 KBytes
[ 5] 1.00-2.00 sec 10.6 MBytes 89.1 Mbits/sec 0 339 KBytes
[ 5] 2.00-3.00 sec 10.6 MBytes 89.1 Mbits/sec 0 386 KBytes
[ 5] 3.00-4.00 sec 10.6 MBytes 89.1 Mbits/sec 0 386 KBytes
[ 5] 4.00-5.00 sec 10.2 MBytes 86.0 Mbits/sec 0 427 KBytes
After (MCS9):
[ 5] 0.00-1.00 sec 33.9 MBytes 284 Mbits/sec 0 771 KBytes
[ 5] 1.00-2.00 sec 31.6 MBytes 265 Mbits/sec 0 865 KBytes
[ 5] 2.00-3.00 sec 29.9 MBytes 251 Mbits/sec 0 963 KBytes
[ 5] 3.00-4.00 sec 28.2 MBytes 237 Mbits/sec 0 963 KBytes
[ 5] 4.00-5.00 sec 26.8 MBytes 224 Mbits/sec 0 963 KBytes
Fixes: 39f40710d0b5 ("rtlwifi: rtl88821ae: Remove usage of private bit manipulation macros")
Cc: stable@vger.kernel.org
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/754785b3-8a78-4554-b80d-de5f603b410b@gmail.com
---
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
index c269942b3f4a..af8d17b9e012 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
@@ -197,9 +197,9 @@ enum rtl8821a_h2c_cmd {
/* _MEDIA_STATUS_RPT_PARM_CMD1 */
#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__cmd, __value) \
- u8p_replace_bits(__cmd + 1, __value, BIT(0))
+ u8p_replace_bits(__cmd, __value, BIT(0))
#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__cmd, __value) \
- u8p_replace_bits(__cmd + 1, __value, BIT(1))
+ u8p_replace_bits(__cmd, __value, BIT(1))
/* AP_OFFLOAD */
#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \
--
2.43.0

View File

@ -0,0 +1,33 @@
From 59ab27a9f20f8de6f7989e8a8c3d97c04ed8199c Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Wed, 18 Dec 2024 02:13:22 +0200
Subject: [PATCH 31/35] wifi: rtw88: 8812a: Support RFE type 2
RF front end type 2 exists in the wild and can be treated like types
0 and 1.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/2917c7fc-6d88-4007-b6a6-9130bd1991e5@gmail.com
---
drivers/net/wireless/realtek/rtw88/rtw8812a.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
index 482edd31823d..d8f0ed70777f 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
@@ -985,6 +985,9 @@ static const struct rtw_rfe_def rtw8812a_rfe_defs[] = {
[1] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl,
.txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
.pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, },
+ [2] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, },
[3] = { .phy_pg_tbl = &rtw8812a_bb_pg_rfe3_tbl,
.txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
.pwr_track_tbl = &rtw8812a_rtw_pwr_track_rfe3_tbl, },
--
2.43.0

View File

@ -0,0 +1,58 @@
From 74a72c367573ad521becf6cc4d649e14387b3c64 Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Wed, 18 Dec 2024 02:16:11 +0200
Subject: [PATCH 32/35] wifi: rtw88: 8821a/8812a: Set ptct_efuse_size to 0
Some RTL8812AU devices fail to probe:
[ 12.478774] rtw_8812au 1-1.3:1.0: failed to dump efuse logical map
[ 12.487712] rtw_8812au 1-1.3:1.0: failed to setup chip efuse info
[ 12.487742] rtw_8812au 1-1.3:1.0: failed to setup chip information
[ 12.491077] rtw_8812au: probe of 1-1.3:1.0 failed with error -22
It turns out these chips don't need to "protect" any bytes at the end of
the efuse.
The original value of 96 was copied from rtw8821c.c.
No one reported any failures with RTL8821AU yet, but the vendor driver
uses the same efuse reading code for both chips.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/1a477adb-60c3-463c-b158-3f86c94cb821@gmail.com
---
drivers/net/wireless/realtek/rtw88/rtw8812a.c | 2 +-
drivers/net/wireless/realtek/rtw88/rtw8821a.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
index d8f0ed70777f..21795286a1a0 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
@@ -1027,7 +1027,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = {
.rx_buf_desc_sz = 8,
.phy_efuse_size = 512,
.log_efuse_size = 512,
- .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
+ .ptct_efuse_size = 0,
.txff_size = 131072,
.rxff_size = 16128,
.rsvd_drv_pg_num = 9,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
index db242c9ad68f..dafab2af33bc 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
@@ -1118,7 +1118,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = {
.rx_buf_desc_sz = 8,
.phy_efuse_size = 512,
.log_efuse_size = 512,
- .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
+ .ptct_efuse_size = 0,
.txff_size = 65536,
.rxff_size = 16128,
.rsvd_drv_pg_num = 8,
--
2.43.0

View File

@ -0,0 +1,135 @@
From e9048e2935f7d797c2ba047c15b705b57c2fa99a Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Thu, 19 Dec 2024 00:33:20 +0200
Subject: [PATCH 33/35] wifi: rtw88: usb: Copy instead of cloning the RX skb
"iperf3 -c 192.168.0.1 -R --udp -b 0" shows about 40% of datagrams
are lost. Many torrents don't download faster than 3 MiB/s, probably
because the Bittorrent protocol uses UDP. This is somehow related to
the use of skb_clone() in the RX path.
Don't use skb_clone(). Instead allocate a new skb for each 802.11 frame
received and copy the data from the big (32768 byte) skb.
With this patch, "iperf3 -c 192.168.0.1 -R --udp -b 0" shows only 1-2%
of datagrams are lost, and torrents can reach download speeds of 36
MiB/s.
Tested with RTL8812AU and RTL8822CU.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/8c9d4f9d-ebd8-4dc0-a0c4-9ebe430521dd@gmail.com
---
drivers/net/wireless/realtek/rtw88/usb.c | 52 ++++++++++++++----------
1 file changed, 31 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index be193c7add77..28679d9cdffc 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -7,6 +7,7 @@
#include <linux/mutex.h>
#include "main.h"
#include "debug.h"
+#include "mac.h"
#include "reg.h"
#include "tx.h"
#include "rx.h"
@@ -547,49 +548,58 @@ static void rtw_usb_rx_handler(struct work_struct *work)
{
struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work);
struct rtw_dev *rtwdev = rtwusb->rtwdev;
- const struct rtw_chip_info *chip = rtwdev->chip;
- u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
struct ieee80211_rx_status rx_status;
- u32 pkt_offset, next_pkt, urb_len;
struct rtw_rx_pkt_stat pkt_stat;
- struct sk_buff *next_skb;
+ struct sk_buff *rx_skb;
struct sk_buff *skb;
+ u32 pkt_desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+ u32 max_skb_len = pkt_desc_sz + PHY_STATUS_SIZE * 8 +
+ IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ u32 pkt_offset, next_pkt, skb_len;
u8 *rx_desc;
int limit;
for (limit = 0; limit < 200; limit++) {
- skb = skb_dequeue(&rtwusb->rx_queue);
- if (!skb)
+ rx_skb = skb_dequeue(&rtwusb->rx_queue);
+ if (!rx_skb)
break;
if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n");
- dev_kfree_skb_any(skb);
+ dev_kfree_skb_any(rx_skb);
continue;
}
- urb_len = skb->len;
+ rx_desc = rx_skb->data;
do {
- rx_desc = skb->data;
rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat,
&rx_status);
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
pkt_stat.shift;
- next_pkt = round_up(pkt_stat.pkt_len + pkt_offset, 8);
+ skb_len = pkt_stat.pkt_len + pkt_offset;
+ if (skb_len > max_skb_len) {
+ rtw_dbg(rtwdev, RTW_DBG_USB,
+ "skipping too big packet: %u\n",
+ skb_len);
+ goto skip_packet;
+ }
- if (urb_len >= next_pkt + pkt_desc_sz)
- next_skb = skb_clone(skb, GFP_KERNEL);
- else
- next_skb = NULL;
+ skb = alloc_skb(skb_len, GFP_KERNEL);
+ if (!skb) {
+ rtw_dbg(rtwdev, RTW_DBG_USB,
+ "failed to allocate RX skb of size %u\n",
+ skb_len);
+ goto skip_packet;
+ }
+
+ skb_put_data(skb, rx_desc, skb_len);
if (pkt_stat.is_c2h) {
- skb_trim(skb, pkt_stat.pkt_len + pkt_offset);
rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
} else {
skb_pull(skb, pkt_offset);
- skb_trim(skb, pkt_stat.pkt_len);
rtw_update_rx_freq_for_invalid(rtwdev, skb,
&rx_status,
&pkt_stat);
@@ -598,12 +608,12 @@ static void rtw_usb_rx_handler(struct work_struct *work)
ieee80211_rx_irqsafe(rtwdev->hw, skb);
}
- skb = next_skb;
- if (skb)
- skb_pull(skb, next_pkt);
+skip_packet:
+ next_pkt = round_up(skb_len, 8);
+ rx_desc += next_pkt;
+ } while (rx_desc + pkt_desc_sz < rx_skb->data + rx_skb->len);
- urb_len -= next_pkt;
- } while (skb);
+ dev_kfree_skb_any(rx_skb);
}
}
--
2.43.0

View File

@ -0,0 +1,51 @@
From 13221be72034d1c34630ab124c43438aefe7e656 Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Thu, 19 Dec 2024 00:34:42 +0200
Subject: [PATCH 34/35] wifi: rtw88: Handle C2H_ADAPTIVITY in
rtw_fw_c2h_cmd_handle()
The firmware message C2H_ADAPTIVITY is currently handled in
rtw_fw_c2h_cmd_rx_irqsafe(), which runs in the RX workqueue, but it's
not "irqsafe" with USB because it sleeps (reads hardware registers).
This becomes a problem after the next patch, which will create the RX
workqueue with the flag WQ_BH.
To avoid sleeping when it's not allowed, handle C2H_ADAPTIVITY in
rtw_fw_c2h_cmd_handle(), which runs in the c2h workqueue.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/96e52b03-be8d-4050-ae71-bfdb478ff42f@gmail.com
---
drivers/net/wireless/realtek/rtw88/fw.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index e6e9946fbf44..02389b7c6876 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -332,6 +332,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
case C2H_RA_RPT:
rtw_fw_ra_report_handle(rtwdev, c2h->payload, len);
break;
+ case C2H_ADAPTIVITY:
+ rtw_fw_adaptivity_result(rtwdev, c2h->payload, len);
+ break;
default:
rtw_dbg(rtwdev, RTW_DBG_FW, "C2H 0x%x isn't handled\n", c2h->id);
break;
@@ -367,10 +370,6 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
rtw_fw_scan_result(rtwdev, c2h->payload, len);
dev_kfree_skb_any(skb);
break;
- case C2H_ADAPTIVITY:
- rtw_fw_adaptivity_result(rtwdev, c2h->payload, len);
- dev_kfree_skb_any(skb);
- break;
default:
/* pass offset for further operation */
*((u32 *)skb->cb) = pkt_offset;
--
2.43.0

View File

@ -0,0 +1,230 @@
From 3e3aa566dd1803f1697530de6c8489a8350765b3 Mon Sep 17 00:00:00 2001
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Date: Thu, 19 Dec 2024 00:35:49 +0200
Subject: [PATCH 35/35] wifi: rtw88: usb: Preallocate and reuse the RX skbs
The USB driver uses four USB Request Blocks for RX. Before submitting
one, it allocates a 32768 byte skb for the RX data. This allocation can
fail, maybe due to temporary memory fragmentation. When the allocation
fails, the corresponding URB is never submitted again. After four such
allocation failures, all RX stops because the driver is not requesting
data from the device anymore.
Don't allocate a 32768 byte skb when submitting a USB Request Block
(which happens very often). Instead preallocate 8 such skbs, and reuse
them over and over. If all 8 are busy, allocate a new one. This is
pretty rare. If the allocation fails, use a work to try again later.
When there are enough free skbs again, free the excess skbs.
Also, use WQ_BH for the RX workqueue. With a normal or high priority
workqueue the skbs are processed too slowly when the system is even a
little busy, like when opening a new page in a browser, and the driver
runs out of free skbs and allocates a lot of new ones.
This is more or less what the out-of-tree Realtek drivers do, except
they use a tasklet instead of a BH workqueue.
Tested with RTL8723DU, RTL8821AU, RTL8812AU, RTL8812BU, RTL8822CU,
RTL8811CU.
Closes: https://lore.kernel.org/linux-wireless/6e7ecb47-7ea0-433a-a19f-05f88a2edf6b@gmail.com/
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/9cee7a34-c38d-4128-824d-0ec139ca5a4e@gmail.com
---
drivers/net/wireless/realtek/rtw88/usb.c | 79 +++++++++++++++++++-----
drivers/net/wireless/realtek/rtw88/usb.h | 3 +
2 files changed, 67 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 28679d9cdffc..1572b61cf877 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -586,7 +586,7 @@ static void rtw_usb_rx_handler(struct work_struct *work)
goto skip_packet;
}
- skb = alloc_skb(skb_len, GFP_KERNEL);
+ skb = alloc_skb(skb_len, GFP_ATOMIC);
if (!skb) {
rtw_dbg(rtwdev, RTW_DBG_USB,
"failed to allocate RX skb of size %u\n",
@@ -613,32 +613,70 @@ static void rtw_usb_rx_handler(struct work_struct *work)
rx_desc += next_pkt;
} while (rx_desc + pkt_desc_sz < rx_skb->data + rx_skb->len);
- dev_kfree_skb_any(rx_skb);
+ if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW_USB_RX_SKB_NUM)
+ dev_kfree_skb_any(rx_skb);
+ else
+ skb_queue_tail(&rtwusb->rx_free_queue, rx_skb);
}
}
static void rtw_usb_read_port_complete(struct urb *urb);
-static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
+static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb,
+ struct rx_usb_ctrl_block *rxcb,
+ gfp_t gfp)
{
struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ struct sk_buff *rx_skb;
int error;
- rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
- if (!rxcb->rx_skb)
- return;
+ rx_skb = skb_dequeue(&rtwusb->rx_free_queue);
+ if (!rx_skb)
+ rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, gfp);
+
+ if (!rx_skb)
+ goto try_later;
+
+ skb_reset_tail_pointer(rx_skb);
+ rx_skb->len = 0;
+
+ rxcb->rx_skb = rx_skb;
usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
rtw_usb_read_port_complete, rxcb);
- error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
+ error = usb_submit_urb(rxcb->rx_urb, gfp);
if (error) {
- kfree_skb(rxcb->rx_skb);
+ skb_queue_tail(&rtwusb->rx_free_queue, rxcb->rx_skb);
+
if (error != -ENODEV)
rtw_err(rtwdev, "Err sending rx data urb %d\n",
error);
+
+ if (error == -ENOMEM)
+ goto try_later;
+ }
+
+ return;
+
+try_later:
+ rxcb->rx_skb = NULL;
+ queue_work(rtwusb->rxwq, &rtwusb->rx_urb_work);
+}
+
+static void rtw_usb_rx_resubmit_work(struct work_struct *work)
+{
+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_urb_work);
+ struct rx_usb_ctrl_block *rxcb;
+ int i;
+
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+ rxcb = &rtwusb->rx_cb[i];
+
+ if (!rxcb->rx_skb)
+ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC);
}
}
@@ -654,15 +692,16 @@ static void rtw_usb_read_port_complete(struct urb *urb)
urb->actual_length < 24) {
rtw_err(rtwdev, "failed to get urb length:%d\n",
urb->actual_length);
- if (skb)
- dev_kfree_skb_any(skb);
+ skb_queue_tail(&rtwusb->rx_free_queue, skb);
} else {
skb_put(skb, urb->actual_length);
skb_queue_tail(&rtwusb->rx_queue, skb);
queue_work(rtwusb->rxwq, &rtwusb->rx_work);
}
- rtw_usb_rx_resubmit(rtwusb, rxcb);
+ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC);
} else {
+ skb_queue_tail(&rtwusb->rx_free_queue, skb);
+
switch (urb->status) {
case -EINVAL:
case -EPIPE:
@@ -680,8 +719,6 @@ static void rtw_usb_read_port_complete(struct urb *urb)
rtw_err(rtwdev, "status %d\n", urb->status);
break;
}
- if (skb)
- dev_kfree_skb_any(skb);
}
}
@@ -869,16 +906,26 @@ static struct rtw_hci_ops rtw_usb_ops = {
static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct sk_buff *rx_skb;
+ int i;
- rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
+ rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
if (!rtwusb->rxwq) {
rtw_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM;
}
skb_queue_head_init(&rtwusb->rx_queue);
+ skb_queue_head_init(&rtwusb->rx_free_queue);
INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
+ INIT_WORK(&rtwusb->rx_urb_work, rtw_usb_rx_resubmit_work);
+
+ for (i = 0; i < RTW_USB_RX_SKB_NUM; i++) {
+ rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_KERNEL);
+ if (rx_skb)
+ skb_queue_tail(&rtwusb->rx_free_queue, rx_skb);
+ }
return 0;
}
@@ -891,7 +938,7 @@ static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
- rtw_usb_rx_resubmit(rtwusb, rxcb);
+ rtw_usb_rx_resubmit(rtwusb, rxcb, GFP_KERNEL);
}
}
@@ -903,6 +950,8 @@ static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
flush_workqueue(rtwusb->rxwq);
destroy_workqueue(rtwusb->rxwq);
+
+ skb_queue_purge(&rtwusb->rx_free_queue);
}
static int rtw_usb_init_tx(struct rtw_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
index 86697a5c0103..9b695b688b24 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.h
+++ b/drivers/net/wireless/realtek/rtw88/usb.h
@@ -38,6 +38,7 @@
#define RTW_USB_RXAGG_TIMEOUT 10
#define RTW_USB_RXCB_NUM 4
+#define RTW_USB_RX_SKB_NUM 8
#define RTW_USB_EP_MAX 4
@@ -81,7 +82,9 @@ struct rtw_usb {
struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
struct sk_buff_head rx_queue;
+ struct sk_buff_head rx_free_queue;
struct work_struct rx_work;
+ struct work_struct rx_urb_work;
};
static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
--
2.43.0