mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
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:
commit
315c07813d
@ -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
|
||||
|
@ -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
|
||||
|
33
packages/linux/patches/rtlwifi/after-6.12/0031-wifi-rtw88-8812a-Support-RFE-type-2.patch
vendored
Normal file
33
packages/linux/patches/rtlwifi/after-6.12/0031-wifi-rtw88-8812a-Support-RFE-type-2.patch
vendored
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user