1 |
|
2 |
drivers/net/wireless/realtek/rtw88/Kconfig | 47 +++++++++ |
3 |
drivers/net/wireless/realtek/rtw88/Makefile | 15 +++ |
4 |
drivers/net/wireless/realtek/rtw88/coex.c | 3 |
5 |
drivers/net/wireless/realtek/rtw88/debug.c | 15 +++ |
6 |
drivers/net/wireless/realtek/rtw88/fw.c | 31 +++--- |
7 |
drivers/net/wireless/realtek/rtw88/fw.h | 11 ++ |
8 |
drivers/net/wireless/realtek/rtw88/hci.h | 9 - |
9 |
drivers/net/wireless/realtek/rtw88/mac.c | 21 ++++ |
10 |
drivers/net/wireless/realtek/rtw88/mac80211.c | 2 |
11 |
drivers/net/wireless/realtek/rtw88/main.c | 12 +- |
12 |
drivers/net/wireless/realtek/rtw88/main.h | 12 +- |
13 |
drivers/net/wireless/realtek/rtw88/phy.c | 6 - |
14 |
drivers/net/wireless/realtek/rtw88/ps.c | 2 |
15 |
drivers/net/wireless/realtek/rtw88/reg.h | 1 |
16 |
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 28 +++++ |
17 |
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 13 ++ |
18 |
drivers/net/wireless/realtek/rtw88/rtw8723du.c | 36 +++++++ |
19 |
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 18 +++ |
20 |
drivers/net/wireless/realtek/rtw88/rtw8821c.h | 21 ++++ |
21 |
drivers/net/wireless/realtek/rtw88/rtw8821cu.c | 50 ++++++++++ |
22 |
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 19 +++ |
23 |
drivers/net/wireless/realtek/rtw88/rtw8822bu.c | 90 ++++++++++++++++++ |
24 |
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 24 ++++ |
25 |
drivers/net/wireless/realtek/rtw88/rtw8822cu.c | 44 ++++++++ |
26 |
drivers/net/wireless/realtek/rtw88/tx.h | 31 ++++++ |
27 |
drivers/net/wireless/realtek/rtw88/usb.c | 911 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
28 |
drivers/net/wireless/realtek/rtw88/usb.h | 107 +++++++++++++++++++++ |
29 |
drivers/net/wireless/realtek/rtw88/util.c | 103 ++++++++++++++++++++ |
30 |
drivers/net/wireless/realtek/rtw88/util.h | 12 +- |
31 |
29 files changed, 1650 insertions(+), 44 deletions(-) |
32 |
|
33 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/coex.c linux-6.2/drivers/net/wireless/realtek/rtw88/coex.c |
34 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/coex.c 2022-12-12 00:15:18.000000000 +0200 |
35 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/coex.c 2022-12-24 00:49:25.771376835 +0200 |
36 |
@@ -633,7 +633,7 @@ static struct sk_buff *rtw_coex_info_req |
37 |
struct rtw_coex *coex = &rtwdev->coex; |
38 |
struct sk_buff *skb_resp = NULL; |
39 |
|
40 |
- mutex_lock(&coex->mutex); |
41 |
+ lockdep_assert_held(&rtwdev->mutex); |
42 |
|
43 |
rtw_fw_query_bt_mp_info(rtwdev, req); |
44 |
|
45 |
@@ -650,7 +650,6 @@ static struct sk_buff *rtw_coex_info_req |
46 |
} |
47 |
|
48 |
out: |
49 |
- mutex_unlock(&coex->mutex); |
50 |
return skb_resp; |
51 |
} |
52 |
|
53 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/debug.c linux-6.2/drivers/net/wireless/realtek/rtw88/debug.c |
54 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/debug.c 2022-12-12 00:15:18.000000000 +0200 |
55 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/debug.c 2022-12-24 00:49:25.771376835 +0200 |
56 |
@@ -144,7 +144,9 @@ static int rtw_debugfs_get_rf_read(struc |
57 |
addr = debugfs_priv->rf_addr; |
58 |
mask = debugfs_priv->rf_mask; |
59 |
|
60 |
+ mutex_lock(&rtwdev->mutex); |
61 |
val = rtw_read_rf(rtwdev, path, addr, mask); |
62 |
+ mutex_unlock(&rtwdev->mutex); |
63 |
|
64 |
seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", |
65 |
path, addr, mask, val); |
66 |
@@ -390,7 +392,9 @@ static ssize_t rtw_debugfs_set_h2c(struc |
67 |
return -EINVAL; |
68 |
} |
69 |
|
70 |
+ mutex_lock(&rtwdev->mutex); |
71 |
rtw_fw_h2c_cmd_dbg(rtwdev, param); |
72 |
+ mutex_unlock(&rtwdev->mutex); |
73 |
|
74 |
return count; |
75 |
} |
76 |
@@ -414,7 +418,9 @@ static ssize_t rtw_debugfs_set_rf_write( |
77 |
return count; |
78 |
} |
79 |
|
80 |
+ mutex_lock(&rtwdev->mutex); |
81 |
rtw_write_rf(rtwdev, path, addr, mask, val); |
82 |
+ mutex_unlock(&rtwdev->mutex); |
83 |
rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, |
84 |
"write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", |
85 |
path, addr, mask, val); |
86 |
@@ -519,6 +525,8 @@ static int rtw_debug_get_rf_dump(struct |
87 |
u32 addr, offset, data; |
88 |
u8 path; |
89 |
|
90 |
+ mutex_lock(&rtwdev->mutex); |
91 |
+ |
92 |
for (path = 0; path < rtwdev->hal.rf_path_num; path++) { |
93 |
seq_printf(m, "RF path:%d\n", path); |
94 |
for (addr = 0; addr < 0x100; addr += 4) { |
95 |
@@ -533,6 +541,8 @@ static int rtw_debug_get_rf_dump(struct |
96 |
seq_puts(m, "\n"); |
97 |
} |
98 |
|
99 |
+ mutex_unlock(&rtwdev->mutex); |
100 |
+ |
101 |
return 0; |
102 |
} |
103 |
|
104 |
@@ -831,7 +841,9 @@ static int rtw_debugfs_get_coex_info(str |
105 |
struct rtw_debugfs_priv *debugfs_priv = m->private; |
106 |
struct rtw_dev *rtwdev = debugfs_priv->rtwdev; |
107 |
|
108 |
+ mutex_lock(&rtwdev->mutex); |
109 |
rtw_coex_display_coex_info(rtwdev, m); |
110 |
+ mutex_unlock(&rtwdev->mutex); |
111 |
|
112 |
return 0; |
113 |
} |
114 |
@@ -1026,6 +1038,8 @@ static void dump_gapk_status(struct rtw_ |
115 |
dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+', |
116 |
rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]); |
117 |
|
118 |
+ mutex_lock(&rtwdev->mutex); |
119 |
+ |
120 |
for (path = 0; path < rtwdev->hal.rf_path_num; path++) { |
121 |
val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK); |
122 |
seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val); |
123 |
@@ -1035,6 +1049,7 @@ static void dump_gapk_status(struct rtw_ |
124 |
txgapk->rf3f_fs[path][i], i); |
125 |
seq_puts(m, "\n"); |
126 |
} |
127 |
+ mutex_unlock(&rtwdev->mutex); |
128 |
} |
129 |
|
130 |
static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v) |
131 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/fw.c linux-6.2/drivers/net/wireless/realtek/rtw88/fw.c |
132 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/fw.c 2022-12-12 00:15:18.000000000 +0200 |
133 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/fw.c 2022-12-24 00:49:25.771376835 +0200 |
134 |
@@ -311,10 +311,10 @@ EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr); |
135 |
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, |
136 |
u8 *h2c) |
137 |
{ |
138 |
+ struct rtw_h2c_cmd *h2c_cmd = (struct rtw_h2c_cmd *)h2c; |
139 |
u8 box; |
140 |
u8 box_state; |
141 |
u32 box_reg, box_ex_reg; |
142 |
- int idx; |
143 |
int ret; |
144 |
|
145 |
rtw_dbg(rtwdev, RTW_DBG_FW, |
146 |
@@ -322,7 +322,7 @@ static void rtw_fw_send_h2c_command(stru |
147 |
h2c[3], h2c[2], h2c[1], h2c[0], |
148 |
h2c[7], h2c[6], h2c[5], h2c[4]); |
149 |
|
150 |
- spin_lock(&rtwdev->h2c.lock); |
151 |
+ lockdep_assert_held(&rtwdev->mutex); |
152 |
|
153 |
box = rtwdev->h2c.last_box_num; |
154 |
switch (box) { |
155 |
@@ -344,7 +344,7 @@ static void rtw_fw_send_h2c_command(stru |
156 |
break; |
157 |
default: |
158 |
WARN(1, "invalid h2c mail box number\n"); |
159 |
- goto out; |
160 |
+ return; |
161 |
} |
162 |
|
163 |
ret = read_poll_timeout_atomic(rtw_read8, box_state, |
164 |
@@ -353,19 +353,14 @@ static void rtw_fw_send_h2c_command(stru |
165 |
|
166 |
if (ret) { |
167 |
rtw_err(rtwdev, "failed to send h2c command\n"); |
168 |
- goto out; |
169 |
+ return; |
170 |
} |
171 |
|
172 |
- for (idx = 0; idx < 4; idx++) |
173 |
- rtw_write8(rtwdev, box_reg + idx, h2c[idx]); |
174 |
- for (idx = 0; idx < 4; idx++) |
175 |
- rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]); |
176 |
+ rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext)); |
177 |
+ rtw_write32(rtwdev, box_reg, le32_to_cpu(h2c_cmd->msg)); |
178 |
|
179 |
if (++rtwdev->h2c.last_box_num >= 4) |
180 |
rtwdev->h2c.last_box_num = 0; |
181 |
- |
182 |
-out: |
183 |
- spin_unlock(&rtwdev->h2c.lock); |
184 |
} |
185 |
|
186 |
void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c) |
187 |
@@ -377,15 +372,13 @@ static void rtw_fw_send_h2c_packet(struc |
188 |
{ |
189 |
int ret; |
190 |
|
191 |
- spin_lock(&rtwdev->h2c.lock); |
192 |
+ lockdep_assert_held(&rtwdev->mutex); |
193 |
|
194 |
FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq); |
195 |
ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE); |
196 |
if (ret) |
197 |
rtw_err(rtwdev, "failed to send h2c packet\n"); |
198 |
rtwdev->h2c.seq++; |
199 |
- |
200 |
- spin_unlock(&rtwdev->h2c.lock); |
201 |
} |
202 |
|
203 |
void |
204 |
@@ -823,6 +816,16 @@ void rtw_fw_set_nlo_info(struct rtw_dev |
205 |
|
206 |
rtw_fw_send_h2c_command(rtwdev, h2c_pkt); |
207 |
} |
208 |
+ |
209 |
+void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev) |
210 |
+{ |
211 |
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0}; |
212 |
+ |
213 |
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RECOVER_BT_DEV); |
214 |
+ SET_RECOVER_BT_DEV_EN(h2c_pkt, 1); |
215 |
+ |
216 |
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); |
217 |
+} |
218 |
|
219 |
void rtw_fw_set_pg_info(struct rtw_dev *rtwdev) |
220 |
{ |
221 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/fw.h linux-6.2/drivers/net/wireless/realtek/rtw88/fw.h |
222 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/fw.h 2022-12-12 00:15:18.000000000 +0200 |
223 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/fw.h 2022-12-24 00:49:25.771376835 +0200 |
224 |
@@ -81,6 +81,11 @@ struct rtw_c2h_adaptivity { |
225 |
u8 option; |
226 |
} __packed; |
227 |
|
228 |
+struct rtw_h2c_cmd { |
229 |
+ __le32 msg; |
230 |
+ __le32 msg_ext; |
231 |
+} __packed; |
232 |
+ |
233 |
enum rtw_rsvd_packet_type { |
234 |
RSVD_BEACON, |
235 |
RSVD_DUMMY, |
236 |
@@ -550,6 +555,8 @@ static inline void rtw_h2c_pkt_set_heade |
237 |
#define H2C_CMD_AOAC_GLOBAL_INFO 0x82 |
238 |
#define H2C_CMD_NLO_INFO 0x8C |
239 |
|
240 |
+#define H2C_CMD_RECOVER_BT_DEV 0xD1 |
241 |
+ |
242 |
#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ |
243 |
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) |
244 |
|
245 |
@@ -749,6 +756,9 @@ static inline void rtw_h2c_pkt_set_heade |
246 |
#define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \ |
247 |
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) |
248 |
|
249 |
+#define SET_RECOVER_BT_DEV_EN(h2c_pkt, value) \ |
250 |
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) |
251 |
+ |
252 |
#define GET_FW_DUMP_LEN(_header) \ |
253 |
le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(15, 0)) |
254 |
#define GET_FW_DUMP_SEQ(_header) \ |
255 |
@@ -838,6 +848,7 @@ void rtw_fw_set_aoac_global_info_cmd(str |
256 |
u8 group_key_enc); |
257 |
|
258 |
void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable); |
259 |
+void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev); |
260 |
void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev, |
261 |
struct cfg80211_ssid *ssid); |
262 |
void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable); |
263 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/hci.h linux-6.2/drivers/net/wireless/realtek/rtw88/hci.h |
264 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/hci.h 2022-12-12 00:15:18.000000000 +0200 |
265 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/hci.h 2022-12-24 00:49:25.771376835 +0200 |
266 |
@@ -166,12 +166,11 @@ static inline u32 |
267 |
rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
268 |
u32 addr, u32 mask) |
269 |
{ |
270 |
- unsigned long flags; |
271 |
u32 val; |
272 |
|
273 |
- spin_lock_irqsave(&rtwdev->rf_lock, flags); |
274 |
+ lockdep_assert_held(&rtwdev->mutex); |
275 |
+ |
276 |
val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask); |
277 |
- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); |
278 |
|
279 |
return val; |
280 |
} |
281 |
@@ -180,11 +179,9 @@ static inline void |
282 |
rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
283 |
u32 addr, u32 mask, u32 data) |
284 |
{ |
285 |
- unsigned long flags; |
286 |
+ lockdep_assert_held(&rtwdev->mutex); |
287 |
|
288 |
- spin_lock_irqsave(&rtwdev->rf_lock, flags); |
289 |
rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data); |
290 |
- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); |
291 |
} |
292 |
|
293 |
static inline u32 |
294 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/Kconfig linux-6.2/drivers/net/wireless/realtek/rtw88/Kconfig |
295 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/Kconfig 2022-12-12 00:15:18.000000000 +0200 |
296 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/Kconfig 2022-12-24 00:49:25.770376835 +0200 |
297 |
@@ -16,6 +16,9 @@ config RTW88_CORE |
298 |
config RTW88_PCI |
299 |
tristate |
300 |
|
301 |
+config RTW88_USB |
302 |
+ tristate |
303 |
+ |
304 |
config RTW88_8822B |
305 |
tristate |
306 |
|
307 |
@@ -39,6 +42,17 @@ config RTW88_8822BE |
308 |
|
309 |
802.11ac PCIe wireless network adapter |
310 |
|
311 |
+config RTW88_8822BU |
312 |
+ tristate "Realtek 8822BU USB wireless network adapter" |
313 |
+ depends on USB |
314 |
+ select RTW88_CORE |
315 |
+ select RTW88_USB |
316 |
+ select RTW88_8822B |
317 |
+ help |
318 |
+ Select this option will enable support for 8822BU chipset |
319 |
+ |
320 |
+ 802.11ac USB wireless network adapter |
321 |
+ |
322 |
config RTW88_8822CE |
323 |
tristate "Realtek 8822CE PCI wireless network adapter" |
324 |
depends on PCI |
325 |
@@ -50,6 +64,17 @@ config RTW88_8822CE |
326 |
|
327 |
802.11ac PCIe wireless network adapter |
328 |
|
329 |
+config RTW88_8822CU |
330 |
+ tristate "Realtek 8822CU USB wireless network adapter" |
331 |
+ depends on USB |
332 |
+ select RTW88_CORE |
333 |
+ select RTW88_USB |
334 |
+ select RTW88_8822C |
335 |
+ help |
336 |
+ Select this option will enable support for 8822CU chipset |
337 |
+ |
338 |
+ 802.11ac USB wireless network adapter |
339 |
+ |
340 |
config RTW88_8723DE |
341 |
tristate "Realtek 8723DE PCI wireless network adapter" |
342 |
depends on PCI |
343 |
@@ -61,6 +86,17 @@ config RTW88_8723DE |
344 |
|
345 |
802.11n PCIe wireless network adapter |
346 |
|
347 |
+config RTW88_8723DU |
348 |
+ tristate "Realtek 8723DU USB wireless network adapter" |
349 |
+ depends on USB |
350 |
+ select RTW88_CORE |
351 |
+ select RTW88_USB |
352 |
+ select RTW88_8723D |
353 |
+ help |
354 |
+ Select this option will enable support for 8723DU chipset |
355 |
+ |
356 |
+ 802.11n USB wireless network adapter |
357 |
+ |
358 |
config RTW88_8821CE |
359 |
tristate "Realtek 8821CE PCI wireless network adapter" |
360 |
depends on PCI |
361 |
@@ -72,6 +108,17 @@ config RTW88_8821CE |
362 |
|
363 |
802.11ac PCIe wireless network adapter |
364 |
|
365 |
+config RTW88_8821CU |
366 |
+ tristate "Realtek 8821CU USB wireless network adapter" |
367 |
+ depends on USB |
368 |
+ select RTW88_CORE |
369 |
+ select RTW88_USB |
370 |
+ select RTW88_8821C |
371 |
+ help |
372 |
+ Select this option will enable support for 8821CU chipset |
373 |
+ |
374 |
+ 802.11ac USB wireless network adapter |
375 |
+ |
376 |
config RTW88_DEBUG |
377 |
bool "Realtek rtw88 debug support" |
378 |
depends on RTW88_CORE |
379 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/mac80211.c linux-6.2/drivers/net/wireless/realtek/rtw88/mac80211.c |
380 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/mac80211.c 2022-12-12 00:15:18.000000000 +0200 |
381 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/mac80211.c 2022-12-24 00:49:25.772376835 +0200 |
382 |
@@ -487,8 +487,8 @@ static int rtw_ops_sta_remove(struct iee |
383 |
{ |
384 |
struct rtw_dev *rtwdev = hw->priv; |
385 |
|
386 |
- rtw_fw_beacon_filter_config(rtwdev, false, vif); |
387 |
mutex_lock(&rtwdev->mutex); |
388 |
+ rtw_fw_beacon_filter_config(rtwdev, false, vif); |
389 |
rtw_sta_remove(rtwdev, sta, true); |
390 |
mutex_unlock(&rtwdev->mutex); |
391 |
|
392 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/mac.c linux-6.2/drivers/net/wireless/realtek/rtw88/mac.c |
393 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/mac.c 2022-12-12 00:15:18.000000000 +0200 |
394 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/mac.c 2022-12-24 00:49:25.772376835 +0200 |
395 |
@@ -906,7 +906,8 @@ out: |
396 |
return ret; |
397 |
} |
398 |
|
399 |
-int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) |
400 |
+static |
401 |
+int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) |
402 |
{ |
403 |
if (rtw_chip_wcpu_11n(rtwdev)) |
404 |
return __rtw_download_firmware_legacy(rtwdev, fw); |
405 |
@@ -914,6 +915,21 @@ int rtw_download_firmware(struct rtw_dev |
406 |
return __rtw_download_firmware(rtwdev, fw); |
407 |
} |
408 |
|
409 |
+int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) |
410 |
+{ |
411 |
+ int ret; |
412 |
+ |
413 |
+ ret = _rtw_download_firmware(rtwdev, fw); |
414 |
+ if (ret) |
415 |
+ return ret; |
416 |
+ |
417 |
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && |
418 |
+ rtwdev->chip->id == RTW_CHIP_TYPE_8821C) |
419 |
+ rtw_fw_set_recover_bt_device(rtwdev); |
420 |
+ |
421 |
+ return 0; |
422 |
+} |
423 |
+ |
424 |
static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) |
425 |
{ |
426 |
const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; |
427 |
@@ -1032,6 +1048,9 @@ static int txdma_queue_mapping(struct rt |
428 |
if (rtw_chip_wcpu_11ac(rtwdev)) |
429 |
rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); |
430 |
|
431 |
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) |
432 |
+ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN); |
433 |
+ |
434 |
return 0; |
435 |
} |
436 |
|
437 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/main.c linux-6.2/drivers/net/wireless/realtek/rtw88/main.c |
438 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/main.c 2022-12-12 00:15:18.000000000 +0200 |
439 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/main.c 2022-12-24 00:49:25.772376835 +0200 |
440 |
@@ -1731,7 +1731,8 @@ static void rtw_load_firmware_cb(const s |
441 |
update_firmware_info(rtwdev, fw); |
442 |
complete_all(&fw->completion); |
443 |
|
444 |
- rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n", |
445 |
+ rtw_info(rtwdev, "%sFirmware version %u.%u.%u, H2C version %u\n", |
446 |
+ fw->type == RTW_WOWLAN_FW ? "WOW " : "", |
447 |
fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); |
448 |
} |
449 |
|
450 |
@@ -1757,6 +1758,7 @@ static int rtw_load_firmware(struct rtw_ |
451 |
return -ENOENT; |
452 |
} |
453 |
|
454 |
+ fw->type = type; |
455 |
fw->rtwdev = rtwdev; |
456 |
init_completion(&fw->completion); |
457 |
|
458 |
@@ -1781,6 +1783,10 @@ static int rtw_chip_parameter_setup(stru |
459 |
rtwdev->hci.rpwm_addr = 0x03d9; |
460 |
rtwdev->hci.cpwm_addr = 0x03da; |
461 |
break; |
462 |
+ case RTW_HCI_TYPE_USB: |
463 |
+ rtwdev->hci.rpwm_addr = 0xfe58; |
464 |
+ rtwdev->hci.cpwm_addr = 0xfe57; |
465 |
+ break; |
466 |
default: |
467 |
rtw_err(rtwdev, "unsupported hci type\n"); |
468 |
return -EINVAL; |
469 |
@@ -2065,13 +2071,10 @@ int rtw_core_init(struct rtw_dev *rtwdev |
470 |
skb_queue_head_init(&rtwdev->coex.queue); |
471 |
skb_queue_head_init(&rtwdev->tx_report.queue); |
472 |
|
473 |
- spin_lock_init(&rtwdev->rf_lock); |
474 |
- spin_lock_init(&rtwdev->h2c.lock); |
475 |
spin_lock_init(&rtwdev->txq_lock); |
476 |
spin_lock_init(&rtwdev->tx_report.q_lock); |
477 |
|
478 |
mutex_init(&rtwdev->mutex); |
479 |
- mutex_init(&rtwdev->coex.mutex); |
480 |
mutex_init(&rtwdev->hal.tx_power_mutex); |
481 |
|
482 |
init_waitqueue_head(&rtwdev->coex.wait); |
483 |
@@ -2143,7 +2146,6 @@ void rtw_core_deinit(struct rtw_dev *rtw |
484 |
} |
485 |
|
486 |
mutex_destroy(&rtwdev->mutex); |
487 |
- mutex_destroy(&rtwdev->coex.mutex); |
488 |
mutex_destroy(&rtwdev->hal.tx_power_mutex); |
489 |
} |
490 |
EXPORT_SYMBOL(rtw_core_deinit); |
491 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/main.h linux-6.2/drivers/net/wireless/realtek/rtw88/main.h |
492 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/main.h 2022-12-12 00:15:18.000000000 +0200 |
493 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/main.h 2022-12-24 00:49:25.773376835 +0200 |
494 |
@@ -871,6 +871,10 @@ struct rtw_chip_ops { |
495 |
bool is_tx2_path); |
496 |
void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path, |
497 |
u8 rx_path, bool is_tx2_path); |
498 |
+ /* for USB/SDIO only */ |
499 |
+ void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev, |
500 |
+ struct rtw_tx_pkt_info *pkt_info, |
501 |
+ u8 *txdesc); |
502 |
|
503 |
/* for coex */ |
504 |
void (*coex_set_init)(struct rtw_dev *rtwdev); |
505 |
@@ -1501,8 +1505,6 @@ struct rtw_coex_stat { |
506 |
}; |
507 |
|
508 |
struct rtw_coex { |
509 |
- /* protects coex info request section */ |
510 |
- struct mutex mutex; |
511 |
struct sk_buff_head queue; |
512 |
wait_queue_head_t wait; |
513 |
|
514 |
@@ -1851,6 +1853,7 @@ struct rtw_fw_state { |
515 |
u16 h2c_version; |
516 |
u32 feature; |
517 |
u32 feature_ext; |
518 |
+ enum rtw_fw_type type; |
519 |
}; |
520 |
|
521 |
enum rtw_sar_sources { |
522 |
@@ -1994,9 +1997,6 @@ struct rtw_dev { |
523 |
/* ensures exclusive access from mac80211 callbacks */ |
524 |
struct mutex mutex; |
525 |
|
526 |
- /* read/write rf register */ |
527 |
- spinlock_t rf_lock; |
528 |
- |
529 |
/* watch dog every 2 sec */ |
530 |
struct delayed_work watch_dog_work; |
531 |
u32 watch_dog_cnt; |
532 |
@@ -2022,8 +2022,6 @@ struct rtw_dev { |
533 |
struct { |
534 |
/* incicate the mail box to use with fw */ |
535 |
u8 last_box_num; |
536 |
- /* protect to send h2c to fw */ |
537 |
- spinlock_t lock; |
538 |
u32 seq; |
539 |
} h2c; |
540 |
|
541 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/Makefile linux-6.2/drivers/net/wireless/realtek/rtw88/Makefile |
542 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/Makefile 2022-12-12 00:15:18.000000000 +0200 |
543 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/Makefile 2022-12-24 00:49:25.770376835 +0200 |
544 |
@@ -26,23 +26,38 @@ rtw88_8822b-objs := rtw8822b.o rtw8822b |
545 |
obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o |
546 |
rtw88_8822be-objs := rtw8822be.o |
547 |
|
548 |
+obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o |
549 |
+rtw88_8822bu-objs := rtw8822bu.o |
550 |
+ |
551 |
obj-$(CONFIG_RTW88_8822C) += rtw88_8822c.o |
552 |
rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o |
553 |
|
554 |
obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o |
555 |
rtw88_8822ce-objs := rtw8822ce.o |
556 |
|
557 |
+obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o |
558 |
+rtw88_8822cu-objs := rtw8822cu.o |
559 |
+ |
560 |
obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o |
561 |
rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o |
562 |
|
563 |
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o |
564 |
rtw88_8723de-objs := rtw8723de.o |
565 |
|
566 |
+obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o |
567 |
+rtw88_8723du-objs := rtw8723du.o |
568 |
+ |
569 |
obj-$(CONFIG_RTW88_8821C) += rtw88_8821c.o |
570 |
rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o |
571 |
|
572 |
obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o |
573 |
rtw88_8821ce-objs := rtw8821ce.o |
574 |
|
575 |
+obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o |
576 |
+rtw88_8821cu-objs := rtw8821cu.o |
577 |
+ |
578 |
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o |
579 |
rtw88_pci-objs := pci.o |
580 |
+ |
581 |
+obj-$(CONFIG_RTW88_USB) += rtw88_usb.o |
582 |
+rtw88_usb-objs := usb.o |
583 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/phy.c linux-6.2/drivers/net/wireless/realtek/rtw88/phy.c |
584 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/phy.c 2022-12-12 00:15:18.000000000 +0200 |
585 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/phy.c 2022-12-24 00:49:25.773376835 +0200 |
586 |
@@ -300,7 +300,7 @@ static void rtw_phy_stat_rssi(struct rtw |
587 |
|
588 |
data.rtwdev = rtwdev; |
589 |
data.min_rssi = U8_MAX; |
590 |
- rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data); |
591 |
+ rtw_iterate_stas(rtwdev, rtw_phy_stat_rssi_iter, &data); |
592 |
|
593 |
dm_info->pre_min_rssi = dm_info->min_rssi; |
594 |
dm_info->min_rssi = data.min_rssi; |
595 |
@@ -544,7 +544,7 @@ static void rtw_phy_ra_info_update(struc |
596 |
if (rtwdev->watch_dog_cnt & 0x3) |
597 |
return; |
598 |
|
599 |
- rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); |
600 |
+ rtw_iterate_stas(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); |
601 |
} |
602 |
|
603 |
static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) |
604 |
@@ -597,7 +597,7 @@ static void rtw_phy_rrsr_update(struct r |
605 |
struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
606 |
|
607 |
dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX; |
608 |
- rtw_iterate_stas_atomic(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); |
609 |
+ rtw_iterate_stas(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); |
610 |
rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min); |
611 |
} |
612 |
|
613 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/ps.c linux-6.2/drivers/net/wireless/realtek/rtw88/ps.c |
614 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/ps.c 2022-12-12 00:15:18.000000000 +0200 |
615 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/ps.c 2022-12-24 00:49:25.773376835 +0200 |
616 |
@@ -61,7 +61,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev |
617 |
return ret; |
618 |
} |
619 |
|
620 |
- rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev); |
621 |
+ rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); |
622 |
|
623 |
rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); |
624 |
|
625 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/reg.h linux-6.2/drivers/net/wireless/realtek/rtw88/reg.h |
626 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/reg.h 2022-12-12 00:15:18.000000000 +0200 |
627 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/reg.h 2022-12-24 00:49:25.773376835 +0200 |
628 |
@@ -184,6 +184,7 @@ |
629 |
#define BIT_TXDMA_VIQ_MAP(x) \ |
630 |
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) |
631 |
#define REG_TXDMA_PQ_MAP 0x010C |
632 |
+#define BIT_RXDMA_ARBBW_EN BIT(0) |
633 |
#define BIT_SHIFT_TXDMA_BEQ_MAP 8 |
634 |
#define BIT_MASK_TXDMA_BEQ_MAP 0x3 |
635 |
#define BIT_TXDMA_BEQ_MAP(x) \ |
636 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723d.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723d.c |
637 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723d.c 2022-12-12 00:15:18.000000000 +0200 |
638 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723d.c 2022-12-24 00:49:25.773376835 +0200 |
639 |
@@ -210,6 +210,12 @@ static void rtw8723de_efuse_parsing(stru |
640 |
ether_addr_copy(efuse->addr, map->e.mac_addr); |
641 |
} |
642 |
|
643 |
+static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse, |
644 |
+ struct rtw8723d_efuse *map) |
645 |
+{ |
646 |
+ ether_addr_copy(efuse->addr, map->u.mac_addr); |
647 |
+} |
648 |
+ |
649 |
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) |
650 |
{ |
651 |
struct rtw_efuse *efuse = &rtwdev->efuse; |
652 |
@@ -239,6 +245,9 @@ static int rtw8723d_read_efuse(struct rt |
653 |
case RTW_HCI_TYPE_PCIE: |
654 |
rtw8723de_efuse_parsing(efuse, map); |
655 |
break; |
656 |
+ case RTW_HCI_TYPE_USB: |
657 |
+ rtw8723du_efuse_parsing(efuse, map); |
658 |
+ break; |
659 |
default: |
660 |
/* unsupported now */ |
661 |
return -ENOTSUPP; |
662 |
@@ -1945,6 +1954,24 @@ static void rtw8723d_pwr_track(struct rt |
663 |
dm_info->pwr_trk_triggered = false; |
664 |
} |
665 |
|
666 |
+static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev, |
667 |
+ struct rtw_tx_pkt_info *pkt_info, |
668 |
+ u8 *txdesc) |
669 |
+{ |
670 |
+ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */ |
671 |
+ __le16 chksum = 0; |
672 |
+ __le16 *data = (__le16 *)(txdesc); |
673 |
+ |
674 |
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000); |
675 |
+ |
676 |
+ while (words--) |
677 |
+ chksum ^= *data++; |
678 |
+ |
679 |
+ chksum = ~chksum; |
680 |
+ |
681 |
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum)); |
682 |
+} |
683 |
+ |
684 |
static struct rtw_chip_ops rtw8723d_ops = { |
685 |
.phy_set_param = rtw8723d_phy_set_param, |
686 |
.read_efuse = rtw8723d_read_efuse, |
687 |
@@ -1965,6 +1992,7 @@ static struct rtw_chip_ops rtw8723d_ops |
688 |
.config_bfee = NULL, |
689 |
.set_gid_table = NULL, |
690 |
.cfg_csi_rate = NULL, |
691 |
+ .fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum, |
692 |
|
693 |
.coex_set_init = rtw8723d_coex_cfg_init, |
694 |
.coex_set_ant_switch = NULL, |
695 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723d.h linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723d.h |
696 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723d.h 2022-12-12 00:15:18.000000000 +0200 |
697 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723d.h 2022-12-24 00:49:25.773376835 +0200 |
698 |
@@ -41,6 +41,14 @@ struct rtw8723de_efuse { |
699 |
u8 sub_device_id[2]; |
700 |
}; |
701 |
|
702 |
+struct rtw8723du_efuse { |
703 |
+ u8 res4[48]; /* 0xd0 */ |
704 |
+ u8 vender_id[2]; /* 0x100 */ |
705 |
+ u8 product_id[2]; /* 0x102 */ |
706 |
+ u8 usb_option; /* 0x104 */ |
707 |
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
708 |
+}; |
709 |
+ |
710 |
struct rtw8723d_efuse { |
711 |
__le16 rtl_id; |
712 |
u8 rsvd[2]; |
713 |
@@ -69,7 +77,10 @@ struct rtw8723d_efuse { |
714 |
u8 rfe_option; |
715 |
u8 country_code[2]; |
716 |
u8 res[3]; |
717 |
- struct rtw8723de_efuse e; |
718 |
+ union { |
719 |
+ struct rtw8723de_efuse e; |
720 |
+ struct rtw8723du_efuse u; |
721 |
+ }; |
722 |
}; |
723 |
|
724 |
extern const struct rtw_chip_info rtw8723d_hw_spec; |
725 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723du.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723du.c |
726 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8723du.c 1970-01-01 02:00:00.000000000 +0200 |
727 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8723du.c 2022-12-24 00:49:25.773376835 +0200 |
728 |
@@ -0,0 +1,36 @@ |
729 |
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
730 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
731 |
+ */ |
732 |
+ |
733 |
+#include <linux/module.h> |
734 |
+#include <linux/usb.h> |
735 |
+#include "main.h" |
736 |
+#include "rtw8723d.h" |
737 |
+#include "usb.h" |
738 |
+ |
739 |
+static const struct usb_device_id rtw_8723du_id_table[] = { |
740 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd723, 0xff, 0xff, 0xff), |
741 |
+ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* 8723DU 1*1 */ |
742 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd611, 0xff, 0xff, 0xff), |
743 |
+ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* Edimax EW-7611ULB V2 */ |
744 |
+ { }, |
745 |
+}; |
746 |
+MODULE_DEVICE_TABLE(usb, rtw_8723du_id_table); |
747 |
+ |
748 |
+static int rtw8723du_probe(struct usb_interface *intf, |
749 |
+ const struct usb_device_id *id) |
750 |
+{ |
751 |
+ return rtw_usb_probe(intf, id); |
752 |
+} |
753 |
+ |
754 |
+static struct usb_driver rtw_8723du_driver = { |
755 |
+ .name = "rtw_8723du", |
756 |
+ .id_table = rtw_8723du_id_table, |
757 |
+ .probe = rtw8723du_probe, |
758 |
+ .disconnect = rtw_usb_disconnect, |
759 |
+}; |
760 |
+module_usb_driver(rtw_8723du_driver); |
761 |
+ |
762 |
+MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>"); |
763 |
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver"); |
764 |
+MODULE_LICENSE("Dual BSD/GPL"); |
765 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821c.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821c.c |
766 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821c.c 2022-12-12 00:15:18.000000000 +0200 |
767 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821c.c 2022-12-24 00:49:25.774376835 +0200 |
768 |
@@ -26,6 +26,12 @@ static void rtw8821ce_efuse_parsing(stru |
769 |
ether_addr_copy(efuse->addr, map->e.mac_addr); |
770 |
} |
771 |
|
772 |
+static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse, |
773 |
+ struct rtw8821c_efuse *map) |
774 |
+{ |
775 |
+ ether_addr_copy(efuse->addr, map->u.mac_addr); |
776 |
+} |
777 |
+ |
778 |
enum rtw8821ce_rf_set { |
779 |
SWITCH_TO_BTG, |
780 |
SWITCH_TO_WLG, |
781 |
@@ -68,6 +74,9 @@ static int rtw8821c_read_efuse(struct rt |
782 |
case RTW_HCI_TYPE_PCIE: |
783 |
rtw8821ce_efuse_parsing(efuse, map); |
784 |
break; |
785 |
+ case RTW_HCI_TYPE_USB: |
786 |
+ rtw8821cu_efuse_parsing(efuse, map); |
787 |
+ break; |
788 |
default: |
789 |
/* unsupported now */ |
790 |
return -ENOTSUPP; |
791 |
@@ -1148,6 +1157,13 @@ static void rtw8821c_phy_cck_pd_set(stru |
792 |
dm_info->cck_pd_default + new_lvl * 2); |
793 |
} |
794 |
|
795 |
+static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, |
796 |
+ struct rtw_tx_pkt_info *pkt_info, |
797 |
+ u8 *txdesc) |
798 |
+{ |
799 |
+ fill_txdesc_checksum_common(txdesc, 16); |
800 |
+} |
801 |
+ |
802 |
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { |
803 |
{0x0086, |
804 |
RTW_PWR_CUT_ALL_MSK, |
805 |
@@ -1521,6 +1537,7 @@ static const struct rtw_rfe_def rtw8821c |
806 |
[2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), |
807 |
[4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2), |
808 |
[6] = RTW_DEF_RFE(8821c, 0, 0), |
809 |
+ [34] = RTW_DEF_RFE(8821c, 0, 0), |
810 |
}; |
811 |
|
812 |
static struct rtw_hw_reg rtw8821c_dig[] = { |
813 |
@@ -1595,6 +1612,7 @@ static struct rtw_chip_ops rtw8821c_ops |
814 |
.config_bfee = rtw8821c_bf_config_bfee, |
815 |
.set_gid_table = rtw_bf_set_gid_table, |
816 |
.cfg_csi_rate = rtw_bf_cfg_csi_rate, |
817 |
+ .fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum, |
818 |
|
819 |
.coex_set_init = rtw8821c_coex_cfg_init, |
820 |
.coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch, |
821 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821c.h linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821c.h |
822 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821c.h 2022-12-12 00:15:18.000000000 +0200 |
823 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821c.h 2022-12-24 00:49:25.774376835 +0200 |
824 |
@@ -9,6 +9,26 @@ |
825 |
|
826 |
#define RCR_VHT_ACK BIT(26) |
827 |
|
828 |
+struct rtw8821cu_efuse { |
829 |
+ u8 res4[4]; /* 0xd0 */ |
830 |
+ u8 usb_optional_function; |
831 |
+ u8 res5[0x1e]; |
832 |
+ u8 res6[2]; |
833 |
+ u8 serial[0x0b]; /* 0xf5 */ |
834 |
+ u8 vid; /* 0x100 */ |
835 |
+ u8 res7; |
836 |
+ u8 pid; |
837 |
+ u8 res8[4]; |
838 |
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
839 |
+ u8 res9[2]; |
840 |
+ u8 vendor_name[0x07]; |
841 |
+ u8 res10[2]; |
842 |
+ u8 device_name[0x14]; |
843 |
+ u8 res11[0xcf]; |
844 |
+ u8 package_type; /* 0x1fb */ |
845 |
+ u8 res12[0x4]; |
846 |
+}; |
847 |
+ |
848 |
struct rtw8821ce_efuse { |
849 |
u8 mac_addr[ETH_ALEN]; /* 0xd0 */ |
850 |
u8 vender_id[2]; |
851 |
@@ -73,6 +93,7 @@ struct rtw8821c_efuse { |
852 |
u8 res[3]; |
853 |
union { |
854 |
struct rtw8821ce_efuse e; |
855 |
+ struct rtw8821cu_efuse u; |
856 |
}; |
857 |
}; |
858 |
|
859 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821cu.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821cu.c |
860 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8821cu.c 1970-01-01 02:00:00.000000000 +0200 |
861 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8821cu.c 2022-12-24 00:49:25.774376835 +0200 |
862 |
@@ -0,0 +1,50 @@ |
863 |
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
864 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
865 |
+ */ |
866 |
+ |
867 |
+#include <linux/module.h> |
868 |
+#include <linux/usb.h> |
869 |
+#include "main.h" |
870 |
+#include "rtw8821c.h" |
871 |
+#include "usb.h" |
872 |
+ |
873 |
+static const struct usb_device_id rtw_8821cu_id_table[] = { |
874 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff), |
875 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
876 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff), |
877 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
878 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff), |
879 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
880 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff), |
881 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
882 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff), |
883 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
884 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff), |
885 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ |
886 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff), |
887 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */ |
888 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff), |
889 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */ |
890 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff), |
891 |
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */ |
892 |
+ {}, |
893 |
+}; |
894 |
+MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table); |
895 |
+ |
896 |
+static int rtw_8821cu_probe(struct usb_interface *intf, |
897 |
+ const struct usb_device_id *id) |
898 |
+{ |
899 |
+ return rtw_usb_probe(intf, id); |
900 |
+} |
901 |
+ |
902 |
+static struct usb_driver rtw_8821cu_driver = { |
903 |
+ .name = "rtw_8821cu", |
904 |
+ .id_table = rtw_8821cu_id_table, |
905 |
+ .probe = rtw_8821cu_probe, |
906 |
+ .disconnect = rtw_usb_disconnect, |
907 |
+}; |
908 |
+module_usb_driver(rtw_8821cu_driver); |
909 |
+ |
910 |
+MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>"); |
911 |
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver"); |
912 |
+MODULE_LICENSE("Dual BSD/GPL"); |
913 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822b.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822b.c |
914 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822b.c 2022-12-12 00:15:18.000000000 +0200 |
915 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822b.c 2022-12-24 00:49:25.774376835 +0200 |
916 |
@@ -26,6 +26,12 @@ static void rtw8822be_efuse_parsing(stru |
917 |
ether_addr_copy(efuse->addr, map->e.mac_addr); |
918 |
} |
919 |
|
920 |
+static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse, |
921 |
+ struct rtw8822b_efuse *map) |
922 |
+{ |
923 |
+ ether_addr_copy(efuse->addr, map->u.mac_addr); |
924 |
+} |
925 |
+ |
926 |
static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) |
927 |
{ |
928 |
struct rtw_efuse *efuse = &rtwdev->efuse; |
929 |
@@ -56,6 +62,9 @@ static int rtw8822b_read_efuse(struct rt |
930 |
case RTW_HCI_TYPE_PCIE: |
931 |
rtw8822be_efuse_parsing(efuse, map); |
932 |
break; |
933 |
+ case RTW_HCI_TYPE_USB: |
934 |
+ rtw8822bu_efuse_parsing(efuse, map); |
935 |
+ break; |
936 |
default: |
937 |
/* unsupported now */ |
938 |
return -ENOTSUPP; |
939 |
@@ -1588,6 +1597,15 @@ static void rtw8822b_adaptivity(struct r |
940 |
rtw_phy_set_edcca_th(rtwdev, l2h, h2l); |
941 |
} |
942 |
|
943 |
+static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev, |
944 |
+ struct rtw_tx_pkt_info *pkt_info, |
945 |
+ u8 *txdesc) |
946 |
+{ |
947 |
+ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */ |
948 |
+ |
949 |
+ fill_txdesc_checksum_common(txdesc, words); |
950 |
+} |
951 |
+ |
952 |
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { |
953 |
{0x0086, |
954 |
RTW_PWR_CUT_ALL_MSK, |
955 |
@@ -2163,6 +2181,7 @@ static struct rtw_chip_ops rtw8822b_ops |
956 |
.cfg_csi_rate = rtw_bf_cfg_csi_rate, |
957 |
.adaptivity_init = rtw8822b_adaptivity_init, |
958 |
.adaptivity = rtw8822b_adaptivity, |
959 |
+ .fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum, |
960 |
|
961 |
.coex_set_init = rtw8822b_coex_cfg_init, |
962 |
.coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch, |
963 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822bu.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822bu.c |
964 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822bu.c 1970-01-01 02:00:00.000000000 +0200 |
965 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822bu.c 2022-12-24 00:49:25.774376835 +0200 |
966 |
@@ -0,0 +1,90 @@ |
967 |
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
968 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
969 |
+ */ |
970 |
+ |
971 |
+#include <linux/module.h> |
972 |
+#include <linux/usb.h> |
973 |
+#include "main.h" |
974 |
+#include "rtw8822b.h" |
975 |
+#include "usb.h" |
976 |
+ |
977 |
+static const struct usb_device_id rtw_8822bu_id_table[] = { |
978 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb812, 0xff, 0xff, 0xff), |
979 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, |
980 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82c, 0xff, 0xff, 0xff), |
981 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, |
982 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2102, 0xff, 0xff, 0xff), |
983 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* CCNC */ |
984 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb822, 0xff, 0xff, 0xff), |
985 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822ULC */ |
986 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc822, 0xff, 0xff, 0xff), |
987 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UTC */ |
988 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd822, 0xff, 0xff, 0xff), |
989 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */ |
990 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe822, 0xff, 0xff, 0xff), |
991 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */ |
992 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xf822, 0xff, 0xff, 0xff), |
993 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UAD */ |
994 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb81a, 0xff, 0xff, 0xff), |
995 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Default ID */ |
996 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff), |
997 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS AC1300 USB-AC55 B1 */ |
998 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x184c, 0xff, 0xff, 0xff), |
999 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS U2 */ |
1000 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x19aa, 0xff, 0xff, 0xff), |
1001 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS - USB-AC58 rev A1 */ |
1002 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1870, 0xff, 0xff, 0xff), |
1003 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */ |
1004 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1874, 0xff, 0xff, 0xff), |
1005 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */ |
1006 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331e, 0xff, 0xff, 0xff), |
1007 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-181 */ |
1008 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff), |
1009 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-182 - D1 */ |
1010 |
+ {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331f, 0xff, 0xff, 0xff), |
1011 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec)}, /* Dlink - DWA-183 D Ver */ |
1012 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), |
1013 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB6400M */ |
1014 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0045, 0xff, 0xff, 0xff), |
1015 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB3600 v2 */ |
1016 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff), |
1017 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U v1 */ |
1018 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff), |
1019 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U Plus v1 */ |
1020 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff), |
1021 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T4U V3 */ |
1022 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff), |
1023 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ |
1024 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0116, 0xff, 0xff, 0xff), |
1025 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ |
1026 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0117, 0xff, 0xff, 0xff), |
1027 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */ |
1028 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9055, 0xff, 0xff, 0xff), |
1029 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Netgear A6150 */ |
1030 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0025, 0xff, 0xff, 0xff), |
1031 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Hawking HW12ACU */ |
1032 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x04ca, 0x8602, 0xff, 0xff, 0xff), |
1033 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */ |
1034 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff), |
1035 |
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */ |
1036 |
+ {}, |
1037 |
+}; |
1038 |
+MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table); |
1039 |
+ |
1040 |
+static int rtw8822bu_probe(struct usb_interface *intf, |
1041 |
+ const struct usb_device_id *id) |
1042 |
+{ |
1043 |
+ return rtw_usb_probe(intf, id); |
1044 |
+} |
1045 |
+ |
1046 |
+static struct usb_driver rtw_8822bu_driver = { |
1047 |
+ .name = "rtw_8822bu", |
1048 |
+ .id_table = rtw_8822bu_id_table, |
1049 |
+ .probe = rtw8822bu_probe, |
1050 |
+ .disconnect = rtw_usb_disconnect, |
1051 |
+}; |
1052 |
+module_usb_driver(rtw_8822bu_driver); |
1053 |
+ |
1054 |
+MODULE_AUTHOR("Realtek Corporation"); |
1055 |
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bu driver"); |
1056 |
+MODULE_LICENSE("Dual BSD/GPL"); |
1057 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822c.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822c.c |
1058 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822c.c 2022-12-12 00:15:18.000000000 +0200 |
1059 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822c.c 2022-12-24 00:49:25.775376835 +0200 |
1060 |
@@ -29,6 +29,12 @@ static void rtw8822ce_efuse_parsing(stru |
1061 |
ether_addr_copy(efuse->addr, map->e.mac_addr); |
1062 |
} |
1063 |
|
1064 |
+static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse, |
1065 |
+ struct rtw8822c_efuse *map) |
1066 |
+{ |
1067 |
+ ether_addr_copy(efuse->addr, map->u.mac_addr); |
1068 |
+} |
1069 |
+ |
1070 |
static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) |
1071 |
{ |
1072 |
struct rtw_efuse *efuse = &rtwdev->efuse; |
1073 |
@@ -58,6 +64,9 @@ static int rtw8822c_read_efuse(struct rt |
1074 |
case RTW_HCI_TYPE_PCIE: |
1075 |
rtw8822ce_efuse_parsing(efuse, map); |
1076 |
break; |
1077 |
+ case RTW_HCI_TYPE_USB: |
1078 |
+ rtw8822cu_efuse_parsing(efuse, map); |
1079 |
+ break; |
1080 |
default: |
1081 |
/* unsupported now */ |
1082 |
return -ENOTSUPP; |
1083 |
@@ -4557,6 +4566,18 @@ static void rtw8822c_adaptivity(struct r |
1084 |
rtw_phy_set_edcca_th(rtwdev, l2h, h2l); |
1085 |
} |
1086 |
|
1087 |
+static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev, |
1088 |
+ struct rtw_tx_pkt_info *pkt_info, |
1089 |
+ u8 *txdesc) |
1090 |
+{ |
1091 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1092 |
+ size_t words; |
1093 |
+ |
1094 |
+ words = (pkt_info->pkt_offset * 8 + chip->tx_pkt_desc_sz) / 2; |
1095 |
+ |
1096 |
+ fill_txdesc_checksum_common(txdesc, words); |
1097 |
+} |
1098 |
+ |
1099 |
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { |
1100 |
{0x0086, |
1101 |
RTW_PWR_CUT_ALL_MSK, |
1102 |
@@ -4895,6 +4916,8 @@ static const struct rtw_rfe_def rtw8822c |
1103 |
[0] = RTW_DEF_RFE(8822c, 0, 0), |
1104 |
[1] = RTW_DEF_RFE(8822c, 0, 0), |
1105 |
[2] = RTW_DEF_RFE(8822c, 0, 0), |
1106 |
+ [3] = RTW_DEF_RFE(8822c, 0, 0), |
1107 |
+ [4] = RTW_DEF_RFE(8822c, 0, 0), |
1108 |
[5] = RTW_DEF_RFE(8822c, 0, 5), |
1109 |
[6] = RTW_DEF_RFE(8822c, 0, 0), |
1110 |
}; |
1111 |
@@ -4978,6 +5001,7 @@ static struct rtw_chip_ops rtw8822c_ops |
1112 |
.cfo_track = rtw8822c_cfo_track, |
1113 |
.config_tx_path = rtw8822c_config_tx_path, |
1114 |
.config_txrx_mode = rtw8822c_config_trx_mode, |
1115 |
+ .fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum, |
1116 |
|
1117 |
.coex_set_init = rtw8822c_coex_cfg_init, |
1118 |
.coex_set_ant_switch = NULL, |
1119 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822cu.c linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822cu.c |
1120 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/rtw8822cu.c 1970-01-01 02:00:00.000000000 +0200 |
1121 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/rtw8822cu.c 2022-12-24 00:49:25.775376835 +0200 |
1122 |
@@ -0,0 +1,44 @@ |
1123 |
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
1124 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
1125 |
+ */ |
1126 |
+ |
1127 |
+#include <linux/module.h> |
1128 |
+#include <linux/usb.h> |
1129 |
+#include "main.h" |
1130 |
+#include "rtw8822c.h" |
1131 |
+#include "usb.h" |
1132 |
+ |
1133 |
+static const struct usb_device_id rtw_8822cu_id_table[] = { |
1134 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), |
1135 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, |
1136 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc812, 0xff, 0xff, 0xff), |
1137 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, |
1138 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82e, 0xff, 0xff, 0xff), |
1139 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, |
1140 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd820, 0xff, 0xff, 0xff), |
1141 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, |
1142 |
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd82b, 0xff, 0xff, 0xff), |
1143 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, |
1144 |
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), |
1145 |
+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */ |
1146 |
+ {}, |
1147 |
+}; |
1148 |
+MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table); |
1149 |
+ |
1150 |
+static int rtw8822bu_probe(struct usb_interface *intf, |
1151 |
+ const struct usb_device_id *id) |
1152 |
+{ |
1153 |
+ return rtw_usb_probe(intf, id); |
1154 |
+} |
1155 |
+ |
1156 |
+static struct usb_driver rtw_8822cu_driver = { |
1157 |
+ .name = "rtw_8822cu", |
1158 |
+ .id_table = rtw_8822cu_id_table, |
1159 |
+ .probe = rtw8822bu_probe, |
1160 |
+ .disconnect = rtw_usb_disconnect, |
1161 |
+}; |
1162 |
+module_usb_driver(rtw_8822cu_driver); |
1163 |
+ |
1164 |
+MODULE_AUTHOR("Realtek Corporation"); |
1165 |
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cu driver"); |
1166 |
+MODULE_LICENSE("Dual BSD/GPL"); |
1167 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/tx.h linux-6.2/drivers/net/wireless/realtek/rtw88/tx.h |
1168 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/tx.h 2022-12-12 00:15:18.000000000 +0200 |
1169 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/tx.h 2022-12-24 00:49:25.775376835 +0200 |
1170 |
@@ -71,6 +71,14 @@ |
1171 |
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15)) |
1172 |
#define SET_TX_DESC_BT_NULL(txdesc, value) \ |
1173 |
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23)) |
1174 |
+#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \ |
1175 |
+ le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0)) |
1176 |
+#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \ |
1177 |
+ le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24)) |
1178 |
+#define GET_TX_DESC_PKT_OFFSET(txdesc) \ |
1179 |
+ le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24)) |
1180 |
+#define GET_TX_DESC_QSEL(txdesc) \ |
1181 |
+ le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8)) |
1182 |
|
1183 |
enum rtw_tx_desc_queue_select { |
1184 |
TX_DESC_QSEL_TID0 = 0, |
1185 |
@@ -123,4 +131,27 @@ rtw_tx_write_data_h2c_get(struct rtw_dev |
1186 |
struct rtw_tx_pkt_info *pkt_info, |
1187 |
u8 *buf, u32 size); |
1188 |
|
1189 |
+static inline |
1190 |
+void fill_txdesc_checksum_common(u8 *txdesc, size_t words) |
1191 |
+{ |
1192 |
+ __le16 chksum = 0; |
1193 |
+ __le16 *data = (__le16 *)(txdesc); |
1194 |
+ |
1195 |
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000); |
1196 |
+ |
1197 |
+ while (words--) |
1198 |
+ chksum ^= *data++; |
1199 |
+ |
1200 |
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum)); |
1201 |
+} |
1202 |
+ |
1203 |
+static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev, |
1204 |
+ struct rtw_tx_pkt_info *pkt_info, |
1205 |
+ u8 *txdesc) |
1206 |
+{ |
1207 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1208 |
+ |
1209 |
+ chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc); |
1210 |
+} |
1211 |
+ |
1212 |
#endif |
1213 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/usb.c linux-6.2/drivers/net/wireless/realtek/rtw88/usb.c |
1214 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/usb.c 1970-01-01 02:00:00.000000000 +0200 |
1215 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/usb.c 2022-12-24 00:49:25.775376835 +0200 |
1216 |
@@ -0,0 +1,911 @@ |
1217 |
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
1218 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
1219 |
+ */ |
1220 |
+ |
1221 |
+#include <linux/module.h> |
1222 |
+#include <linux/usb.h> |
1223 |
+#include <linux/mutex.h> |
1224 |
+#include "main.h" |
1225 |
+#include "debug.h" |
1226 |
+#include "reg.h" |
1227 |
+#include "tx.h" |
1228 |
+#include "rx.h" |
1229 |
+#include "fw.h" |
1230 |
+#include "ps.h" |
1231 |
+#include "usb.h" |
1232 |
+ |
1233 |
+#define RTW_USB_MAX_RXQ_LEN 512 |
1234 |
+ |
1235 |
+struct rtw_usb_txcb { |
1236 |
+ struct rtw_dev *rtwdev; |
1237 |
+ struct sk_buff_head tx_ack_queue; |
1238 |
+}; |
1239 |
+ |
1240 |
+static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb, |
1241 |
+ struct sk_buff *skb, int agg_num) |
1242 |
+{ |
1243 |
+ struct rtw_dev *rtwdev = rtwusb->rtwdev; |
1244 |
+ struct rtw_tx_pkt_info pkt_info; |
1245 |
+ |
1246 |
+ SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num); |
1247 |
+ pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data); |
1248 |
+ rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data); |
1249 |
+} |
1250 |
+ |
1251 |
+static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len) |
1252 |
+{ |
1253 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1254 |
+ struct usb_device *udev = rtwusb->udev; |
1255 |
+ __le32 *data; |
1256 |
+ unsigned long flags; |
1257 |
+ int idx, ret; |
1258 |
+ static int count; |
1259 |
+ |
1260 |
+ spin_lock_irqsave(&rtwusb->usb_lock, flags); |
1261 |
+ |
1262 |
+ idx = rtwusb->usb_data_index; |
1263 |
+ rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1); |
1264 |
+ |
1265 |
+ spin_unlock_irqrestore(&rtwusb->usb_lock, flags); |
1266 |
+ |
1267 |
+ data = &rtwusb->usb_data[idx]; |
1268 |
+ |
1269 |
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
1270 |
+ RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr, |
1271 |
+ RTW_USB_VENQT_CMD_IDX, data, len, 1000); |
1272 |
+ if (ret < 0 && ret != -ENODEV && count++ < 4) |
1273 |
+ rtw_err(rtwdev, "read register 0x%x failed with %d\n", |
1274 |
+ addr, ret); |
1275 |
+ |
1276 |
+ return le32_to_cpu(*data); |
1277 |
+} |
1278 |
+ |
1279 |
+static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr) |
1280 |
+{ |
1281 |
+ return (u8)rtw_usb_read(rtwdev, addr, 1); |
1282 |
+} |
1283 |
+ |
1284 |
+static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr) |
1285 |
+{ |
1286 |
+ return (u16)rtw_usb_read(rtwdev, addr, 2); |
1287 |
+} |
1288 |
+ |
1289 |
+static u32 rtw_usb_read32(struct rtw_dev *rtwdev, u32 addr) |
1290 |
+{ |
1291 |
+ return (u32)rtw_usb_read(rtwdev, addr, 4); |
1292 |
+} |
1293 |
+ |
1294 |
+static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len) |
1295 |
+{ |
1296 |
+ struct rtw_usb *rtwusb = (struct rtw_usb *)rtwdev->priv; |
1297 |
+ struct usb_device *udev = rtwusb->udev; |
1298 |
+ unsigned long flags; |
1299 |
+ __le32 *data; |
1300 |
+ int idx, ret; |
1301 |
+ static int count; |
1302 |
+ |
1303 |
+ spin_lock_irqsave(&rtwusb->usb_lock, flags); |
1304 |
+ |
1305 |
+ idx = rtwusb->usb_data_index; |
1306 |
+ rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1); |
1307 |
+ |
1308 |
+ spin_unlock_irqrestore(&rtwusb->usb_lock, flags); |
1309 |
+ |
1310 |
+ data = &rtwusb->usb_data[idx]; |
1311 |
+ |
1312 |
+ *data = cpu_to_le32(val); |
1313 |
+ |
1314 |
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
1315 |
+ RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, |
1316 |
+ addr, 0, data, len, 30000); |
1317 |
+ if (ret < 0 && ret != -ENODEV && count++ < 4) |
1318 |
+ rtw_err(rtwdev, "write register 0x%x failed with %d\n", |
1319 |
+ addr, ret); |
1320 |
+} |
1321 |
+ |
1322 |
+static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) |
1323 |
+{ |
1324 |
+ rtw_usb_write(rtwdev, addr, val, 1); |
1325 |
+} |
1326 |
+ |
1327 |
+static void rtw_usb_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) |
1328 |
+{ |
1329 |
+ rtw_usb_write(rtwdev, addr, val, 2); |
1330 |
+} |
1331 |
+ |
1332 |
+static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) |
1333 |
+{ |
1334 |
+ rtw_usb_write(rtwdev, addr, val, 4); |
1335 |
+} |
1336 |
+ |
1337 |
+static int rtw_usb_parse(struct rtw_dev *rtwdev, |
1338 |
+ struct usb_interface *interface) |
1339 |
+{ |
1340 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1341 |
+ struct usb_host_interface *host_interface = &interface->altsetting[0]; |
1342 |
+ struct usb_interface_descriptor *interface_desc = &host_interface->desc; |
1343 |
+ struct usb_endpoint_descriptor *endpoint; |
1344 |
+ struct usb_device *usbd = interface_to_usbdev(interface); |
1345 |
+ int num_out_pipes = 0; |
1346 |
+ int i; |
1347 |
+ u8 num; |
1348 |
+ |
1349 |
+ for (i = 0; i < interface_desc->bNumEndpoints; i++) { |
1350 |
+ endpoint = &host_interface->endpoint[i].desc; |
1351 |
+ num = usb_endpoint_num(endpoint); |
1352 |
+ |
1353 |
+ if (usb_endpoint_dir_in(endpoint) && |
1354 |
+ usb_endpoint_xfer_bulk(endpoint)) { |
1355 |
+ if (rtwusb->pipe_in) { |
1356 |
+ rtw_err(rtwdev, "IN pipes overflow\n"); |
1357 |
+ return -EINVAL; |
1358 |
+ } |
1359 |
+ |
1360 |
+ rtwusb->pipe_in = num; |
1361 |
+ } |
1362 |
+ |
1363 |
+ if (usb_endpoint_dir_in(endpoint) && |
1364 |
+ usb_endpoint_xfer_int(endpoint)) { |
1365 |
+ if (rtwusb->pipe_interrupt) { |
1366 |
+ rtw_err(rtwdev, "INT pipes overflow\n"); |
1367 |
+ return -EINVAL; |
1368 |
+ } |
1369 |
+ |
1370 |
+ rtwusb->pipe_interrupt = num; |
1371 |
+ } |
1372 |
+ |
1373 |
+ if (usb_endpoint_dir_out(endpoint) && |
1374 |
+ usb_endpoint_xfer_bulk(endpoint)) { |
1375 |
+ if (num_out_pipes >= ARRAY_SIZE(rtwusb->out_ep)) { |
1376 |
+ rtw_err(rtwdev, "OUT pipes overflow\n"); |
1377 |
+ return -EINVAL; |
1378 |
+ } |
1379 |
+ |
1380 |
+ rtwusb->out_ep[num_out_pipes++] = num; |
1381 |
+ } |
1382 |
+ } |
1383 |
+ |
1384 |
+ switch (usbd->speed) { |
1385 |
+ case USB_SPEED_LOW: |
1386 |
+ case USB_SPEED_FULL: |
1387 |
+ rtwusb->bulkout_size = RTW_USB_FULL_SPEED_BULK_SIZE; |
1388 |
+ break; |
1389 |
+ case USB_SPEED_HIGH: |
1390 |
+ rtwusb->bulkout_size = RTW_USB_HIGH_SPEED_BULK_SIZE; |
1391 |
+ break; |
1392 |
+ case USB_SPEED_SUPER: |
1393 |
+ rtwusb->bulkout_size = RTW_USB_SUPER_SPEED_BULK_SIZE; |
1394 |
+ break; |
1395 |
+ default: |
1396 |
+ rtw_err(rtwdev, "failed to detect usb speed\n"); |
1397 |
+ return -EINVAL; |
1398 |
+ } |
1399 |
+ |
1400 |
+ rtwdev->hci.bulkout_num = num_out_pipes; |
1401 |
+ |
1402 |
+ switch (num_out_pipes) { |
1403 |
+ case 4: |
1404 |
+ case 3: |
1405 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 2; |
1406 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 2; |
1407 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 2; |
1408 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 2; |
1409 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = 1; |
1410 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = 1; |
1411 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = 0; |
1412 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 0; |
1413 |
+ break; |
1414 |
+ case 2: |
1415 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 1; |
1416 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 1; |
1417 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 1; |
1418 |
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 1; |
1419 |
+ break; |
1420 |
+ case 1: |
1421 |
+ break; |
1422 |
+ default: |
1423 |
+ rtw_err(rtwdev, "failed to get out_pipes(%d)\n", num_out_pipes); |
1424 |
+ return -EINVAL; |
1425 |
+ } |
1426 |
+ |
1427 |
+ return 0; |
1428 |
+} |
1429 |
+ |
1430 |
+static void rtw_usb_write_port_tx_complete(struct urb *urb) |
1431 |
+{ |
1432 |
+ struct rtw_usb_txcb *txcb = urb->context; |
1433 |
+ struct rtw_dev *rtwdev = txcb->rtwdev; |
1434 |
+ struct ieee80211_hw *hw = rtwdev->hw; |
1435 |
+ |
1436 |
+ while (true) { |
1437 |
+ struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue); |
1438 |
+ struct ieee80211_tx_info *info; |
1439 |
+ struct rtw_usb_tx_data *tx_data; |
1440 |
+ |
1441 |
+ if (!skb) |
1442 |
+ break; |
1443 |
+ |
1444 |
+ info = IEEE80211_SKB_CB(skb); |
1445 |
+ tx_data = rtw_usb_get_tx_data(skb); |
1446 |
+ |
1447 |
+ /* enqueue to wait for tx report */ |
1448 |
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { |
1449 |
+ rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn); |
1450 |
+ continue; |
1451 |
+ } |
1452 |
+ |
1453 |
+ /* always ACK for others, then they won't be marked as drop */ |
1454 |
+ ieee80211_tx_info_clear_status(info); |
1455 |
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
1456 |
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
1457 |
+ else |
1458 |
+ info->flags |= IEEE80211_TX_STAT_ACK; |
1459 |
+ |
1460 |
+ ieee80211_tx_status_irqsafe(hw, skb); |
1461 |
+ } |
1462 |
+ |
1463 |
+ kfree(txcb); |
1464 |
+} |
1465 |
+ |
1466 |
+static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel) |
1467 |
+{ |
1468 |
+ if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep)) |
1469 |
+ return 0; |
1470 |
+ |
1471 |
+ return rtwusb->qsel_to_ep[qsel]; |
1472 |
+} |
1473 |
+ |
1474 |
+static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *skb, |
1475 |
+ usb_complete_t cb, void *context) |
1476 |
+{ |
1477 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1478 |
+ struct usb_device *usbd = rtwusb->udev; |
1479 |
+ struct urb *urb; |
1480 |
+ unsigned int pipe; |
1481 |
+ int ret; |
1482 |
+ int ep = qsel_to_ep(rtwusb, qsel); |
1483 |
+ |
1484 |
+ pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]); |
1485 |
+ urb = usb_alloc_urb(0, GFP_ATOMIC); |
1486 |
+ if (!urb) |
1487 |
+ return -ENOMEM; |
1488 |
+ |
1489 |
+ usb_fill_bulk_urb(urb, usbd, pipe, skb->data, skb->len, cb, context); |
1490 |
+ ret = usb_submit_urb(urb, GFP_ATOMIC); |
1491 |
+ |
1492 |
+ usb_free_urb(urb); |
1493 |
+ |
1494 |
+ return ret; |
1495 |
+} |
1496 |
+ |
1497 |
+static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list) |
1498 |
+{ |
1499 |
+ struct rtw_dev *rtwdev = rtwusb->rtwdev; |
1500 |
+ struct rtw_usb_txcb *txcb; |
1501 |
+ struct sk_buff *skb_head; |
1502 |
+ struct sk_buff *skb_iter; |
1503 |
+ int agg_num = 0; |
1504 |
+ unsigned int align_next = 0; |
1505 |
+ |
1506 |
+ if (skb_queue_empty(list)) |
1507 |
+ return false; |
1508 |
+ |
1509 |
+ txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC); |
1510 |
+ if (!txcb) |
1511 |
+ return false; |
1512 |
+ |
1513 |
+ txcb->rtwdev = rtwdev; |
1514 |
+ skb_queue_head_init(&txcb->tx_ack_queue); |
1515 |
+ |
1516 |
+ skb_iter = skb_dequeue(list); |
1517 |
+ |
1518 |
+ if (skb_queue_empty(list)) { |
1519 |
+ skb_head = skb_iter; |
1520 |
+ goto queue; |
1521 |
+ } |
1522 |
+ |
1523 |
+ skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ); |
1524 |
+ if (!skb_head) { |
1525 |
+ skb_head = skb_iter; |
1526 |
+ goto queue; |
1527 |
+ } |
1528 |
+ |
1529 |
+ while (skb_iter) { |
1530 |
+ unsigned long flags; |
1531 |
+ |
1532 |
+ skb_put(skb_head, align_next); |
1533 |
+ skb_put_data(skb_head, skb_iter->data, skb_iter->len); |
1534 |
+ |
1535 |
+ align_next = ALIGN(skb_iter->len, 8) - skb_iter->len; |
1536 |
+ |
1537 |
+ agg_num++; |
1538 |
+ |
1539 |
+ skb_queue_tail(&txcb->tx_ack_queue, skb_iter); |
1540 |
+ |
1541 |
+ spin_lock_irqsave(&list->lock, flags); |
1542 |
+ |
1543 |
+ skb_iter = skb_peek(list); |
1544 |
+ |
1545 |
+ if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ) |
1546 |
+ __skb_unlink(skb_iter, list); |
1547 |
+ else |
1548 |
+ skb_iter = NULL; |
1549 |
+ spin_unlock_irqrestore(&list->lock, flags); |
1550 |
+ } |
1551 |
+ |
1552 |
+ if (agg_num > 1) |
1553 |
+ rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num); |
1554 |
+ |
1555 |
+queue: |
1556 |
+ skb_queue_tail(&txcb->tx_ack_queue, skb_head); |
1557 |
+ |
1558 |
+ rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head, |
1559 |
+ rtw_usb_write_port_tx_complete, txcb); |
1560 |
+ |
1561 |
+ return true; |
1562 |
+} |
1563 |
+ |
1564 |
+static void rtw_usb_tx_handler(struct work_struct *work) |
1565 |
+{ |
1566 |
+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work); |
1567 |
+ int i, limit; |
1568 |
+ |
1569 |
+ for (i = ARRAY_SIZE(rtwusb->tx_queue) - 1; i >= 0; i--) { |
1570 |
+ for (limit = 0; limit < 200; limit++) { |
1571 |
+ struct sk_buff_head *list = &rtwusb->tx_queue[i]; |
1572 |
+ |
1573 |
+ if (!rtw_usb_tx_agg_skb(rtwusb, list)) |
1574 |
+ break; |
1575 |
+ } |
1576 |
+ } |
1577 |
+} |
1578 |
+ |
1579 |
+static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb) |
1580 |
+{ |
1581 |
+ int i; |
1582 |
+ |
1583 |
+ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) |
1584 |
+ skb_queue_purge(&rtwusb->tx_queue[i]); |
1585 |
+} |
1586 |
+ |
1587 |
+static void rtw_usb_write_port_complete(struct urb *urb) |
1588 |
+{ |
1589 |
+ struct sk_buff *skb = urb->context; |
1590 |
+ |
1591 |
+ dev_kfree_skb_any(skb); |
1592 |
+} |
1593 |
+ |
1594 |
+static int rtw_usb_write_data(struct rtw_dev *rtwdev, |
1595 |
+ struct rtw_tx_pkt_info *pkt_info, |
1596 |
+ u8 *buf) |
1597 |
+{ |
1598 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1599 |
+ struct sk_buff *skb; |
1600 |
+ unsigned int desclen, headsize, size; |
1601 |
+ u8 qsel; |
1602 |
+ int ret = 0; |
1603 |
+ |
1604 |
+ size = pkt_info->tx_pkt_size; |
1605 |
+ qsel = pkt_info->qsel; |
1606 |
+ desclen = chip->tx_pkt_desc_sz; |
1607 |
+ headsize = pkt_info->offset ? pkt_info->offset : desclen; |
1608 |
+ |
1609 |
+ skb = dev_alloc_skb(headsize + size); |
1610 |
+ if (unlikely(!skb)) |
1611 |
+ return -ENOMEM; |
1612 |
+ |
1613 |
+ skb_reserve(skb, headsize); |
1614 |
+ skb_put_data(skb, buf, size); |
1615 |
+ skb_push(skb, headsize); |
1616 |
+ memset(skb->data, 0, headsize); |
1617 |
+ rtw_tx_fill_tx_desc(pkt_info, skb); |
1618 |
+ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); |
1619 |
+ |
1620 |
+ ret = rtw_usb_write_port(rtwdev, qsel, skb, |
1621 |
+ rtw_usb_write_port_complete, skb); |
1622 |
+ if (unlikely(ret)) |
1623 |
+ rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret); |
1624 |
+ |
1625 |
+ return ret; |
1626 |
+} |
1627 |
+ |
1628 |
+static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, |
1629 |
+ u32 size) |
1630 |
+{ |
1631 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1632 |
+ struct rtw_usb *rtwusb; |
1633 |
+ struct rtw_tx_pkt_info pkt_info = {0}; |
1634 |
+ u32 len, desclen; |
1635 |
+ |
1636 |
+ rtwusb = rtw_get_usb_priv(rtwdev); |
1637 |
+ |
1638 |
+ pkt_info.tx_pkt_size = size; |
1639 |
+ pkt_info.qsel = TX_DESC_QSEL_BEACON; |
1640 |
+ |
1641 |
+ desclen = chip->tx_pkt_desc_sz; |
1642 |
+ len = desclen + size; |
1643 |
+ if (len % rtwusb->bulkout_size == 0) { |
1644 |
+ len += RTW_USB_PACKET_OFFSET_SZ; |
1645 |
+ pkt_info.offset = desclen + RTW_USB_PACKET_OFFSET_SZ; |
1646 |
+ pkt_info.pkt_offset = 1; |
1647 |
+ } else { |
1648 |
+ pkt_info.offset = desclen; |
1649 |
+ } |
1650 |
+ |
1651 |
+ return rtw_usb_write_data(rtwdev, &pkt_info, buf); |
1652 |
+} |
1653 |
+ |
1654 |
+static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) |
1655 |
+{ |
1656 |
+ struct rtw_tx_pkt_info pkt_info = {0}; |
1657 |
+ |
1658 |
+ pkt_info.tx_pkt_size = size; |
1659 |
+ pkt_info.qsel = TX_DESC_QSEL_H2C; |
1660 |
+ |
1661 |
+ return rtw_usb_write_data(rtwdev, &pkt_info, buf); |
1662 |
+} |
1663 |
+ |
1664 |
+static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb) |
1665 |
+{ |
1666 |
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1667 |
+ __le16 fc = hdr->frame_control; |
1668 |
+ u8 qsel; |
1669 |
+ |
1670 |
+ if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) |
1671 |
+ qsel = TX_DESC_QSEL_MGMT; |
1672 |
+ else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK) |
1673 |
+ qsel = skb->priority; |
1674 |
+ else |
1675 |
+ qsel = TX_DESC_QSEL_BEACON; |
1676 |
+ |
1677 |
+ return qsel; |
1678 |
+} |
1679 |
+ |
1680 |
+static int rtw_usb_tx_write(struct rtw_dev *rtwdev, |
1681 |
+ struct rtw_tx_pkt_info *pkt_info, |
1682 |
+ struct sk_buff *skb) |
1683 |
+{ |
1684 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1685 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1686 |
+ struct rtw_usb_tx_data *tx_data; |
1687 |
+ u8 *pkt_desc; |
1688 |
+ int ep; |
1689 |
+ |
1690 |
+ pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); |
1691 |
+ memset(pkt_desc, 0, chip->tx_pkt_desc_sz); |
1692 |
+ pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(skb); |
1693 |
+ ep = qsel_to_ep(rtwusb, pkt_info->qsel); |
1694 |
+ rtw_tx_fill_tx_desc(pkt_info, skb); |
1695 |
+ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data); |
1696 |
+ tx_data = rtw_usb_get_tx_data(skb); |
1697 |
+ tx_data->sn = pkt_info->sn; |
1698 |
+ |
1699 |
+ skb_queue_tail(&rtwusb->tx_queue[ep], skb); |
1700 |
+ |
1701 |
+ return 0; |
1702 |
+} |
1703 |
+ |
1704 |
+static void rtw_usb_tx_kick_off(struct rtw_dev *rtwdev) |
1705 |
+{ |
1706 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1707 |
+ |
1708 |
+ queue_work(rtwusb->txwq, &rtwusb->tx_work); |
1709 |
+} |
1710 |
+ |
1711 |
+static void rtw_usb_rx_handler(struct work_struct *work) |
1712 |
+{ |
1713 |
+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work); |
1714 |
+ struct rtw_dev *rtwdev = rtwusb->rtwdev; |
1715 |
+ const struct rtw_chip_info *chip = rtwdev->chip; |
1716 |
+ struct rtw_rx_pkt_stat pkt_stat; |
1717 |
+ struct ieee80211_rx_status rx_status; |
1718 |
+ struct sk_buff *skb; |
1719 |
+ u32 pkt_desc_sz = chip->rx_pkt_desc_sz; |
1720 |
+ u32 pkt_offset; |
1721 |
+ u8 *rx_desc; |
1722 |
+ int limit; |
1723 |
+ |
1724 |
+ for (limit = 0; limit < 200; limit++) { |
1725 |
+ skb = skb_dequeue(&rtwusb->rx_queue); |
1726 |
+ if (!skb) |
1727 |
+ break; |
1728 |
+ |
1729 |
+ rx_desc = skb->data; |
1730 |
+ chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, |
1731 |
+ &rx_status); |
1732 |
+ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + |
1733 |
+ pkt_stat.shift; |
1734 |
+ |
1735 |
+ if (pkt_stat.is_c2h) { |
1736 |
+ skb_put(skb, pkt_stat.pkt_len + pkt_offset); |
1737 |
+ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb); |
1738 |
+ continue; |
1739 |
+ } |
1740 |
+ |
1741 |
+ if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) { |
1742 |
+ rtw_err(rtwdev, "failed to get rx_queue, overflow\n"); |
1743 |
+ dev_kfree_skb_any(skb); |
1744 |
+ continue; |
1745 |
+ } |
1746 |
+ |
1747 |
+ skb_put(skb, pkt_stat.pkt_len); |
1748 |
+ skb_reserve(skb, pkt_offset); |
1749 |
+ memcpy(skb->cb, &rx_status, sizeof(rx_status)); |
1750 |
+ ieee80211_rx_irqsafe(rtwdev->hw, skb); |
1751 |
+ } |
1752 |
+} |
1753 |
+ |
1754 |
+static void rtw_usb_read_port_complete(struct urb *urb); |
1755 |
+ |
1756 |
+static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb) |
1757 |
+{ |
1758 |
+ struct rtw_dev *rtwdev = rtwusb->rtwdev; |
1759 |
+ int error; |
1760 |
+ |
1761 |
+ rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC); |
1762 |
+ if (!rxcb->rx_skb) |
1763 |
+ return; |
1764 |
+ |
1765 |
+ usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev, |
1766 |
+ usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in), |
1767 |
+ rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ, |
1768 |
+ rtw_usb_read_port_complete, rxcb); |
1769 |
+ |
1770 |
+ error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC); |
1771 |
+ if (error) { |
1772 |
+ kfree_skb(rxcb->rx_skb); |
1773 |
+ if (error != -ENODEV) |
1774 |
+ rtw_err(rtwdev, "Err sending rx data urb %d\n", |
1775 |
+ error); |
1776 |
+ } |
1777 |
+} |
1778 |
+ |
1779 |
+static void rtw_usb_read_port_complete(struct urb *urb) |
1780 |
+{ |
1781 |
+ struct rx_usb_ctrl_block *rxcb = urb->context; |
1782 |
+ struct rtw_dev *rtwdev = rxcb->rtwdev; |
1783 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1784 |
+ struct sk_buff *skb = rxcb->rx_skb; |
1785 |
+ |
1786 |
+ if (urb->status == 0) { |
1787 |
+ if (urb->actual_length >= RTW_USB_MAX_RECVBUF_SZ || |
1788 |
+ urb->actual_length < 24) { |
1789 |
+ rtw_err(rtwdev, "failed to get urb length:%d\n", |
1790 |
+ urb->actual_length); |
1791 |
+ if (skb) |
1792 |
+ dev_kfree_skb_any(skb); |
1793 |
+ } else { |
1794 |
+ skb_queue_tail(&rtwusb->rx_queue, skb); |
1795 |
+ queue_work(rtwusb->rxwq, &rtwusb->rx_work); |
1796 |
+ } |
1797 |
+ rtw_usb_rx_resubmit(rtwusb, rxcb); |
1798 |
+ } else { |
1799 |
+ switch (urb->status) { |
1800 |
+ case -EINVAL: |
1801 |
+ case -EPIPE: |
1802 |
+ case -ENODEV: |
1803 |
+ case -ESHUTDOWN: |
1804 |
+ case -ENOENT: |
1805 |
+ case -EPROTO: |
1806 |
+ case -EILSEQ: |
1807 |
+ case -ETIME: |
1808 |
+ case -ECOMM: |
1809 |
+ case -EOVERFLOW: |
1810 |
+ case -EINPROGRESS: |
1811 |
+ break; |
1812 |
+ default: |
1813 |
+ rtw_err(rtwdev, "status %d\n", urb->status); |
1814 |
+ break; |
1815 |
+ } |
1816 |
+ if (skb) |
1817 |
+ dev_kfree_skb_any(skb); |
1818 |
+ } |
1819 |
+} |
1820 |
+ |
1821 |
+static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb) |
1822 |
+{ |
1823 |
+ struct rx_usb_ctrl_block *rxcb; |
1824 |
+ int i; |
1825 |
+ |
1826 |
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { |
1827 |
+ rxcb = &rtwusb->rx_cb[i]; |
1828 |
+ if (rxcb->rx_urb) |
1829 |
+ usb_kill_urb(rxcb->rx_urb); |
1830 |
+ } |
1831 |
+} |
1832 |
+ |
1833 |
+static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb) |
1834 |
+{ |
1835 |
+ struct rx_usb_ctrl_block *rxcb; |
1836 |
+ int i; |
1837 |
+ |
1838 |
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { |
1839 |
+ rxcb = &rtwusb->rx_cb[i]; |
1840 |
+ if (rxcb->rx_urb) { |
1841 |
+ usb_kill_urb(rxcb->rx_urb); |
1842 |
+ usb_free_urb(rxcb->rx_urb); |
1843 |
+ } |
1844 |
+ } |
1845 |
+} |
1846 |
+ |
1847 |
+static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb) |
1848 |
+{ |
1849 |
+ int i; |
1850 |
+ |
1851 |
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { |
1852 |
+ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; |
1853 |
+ |
1854 |
+ rxcb->n = i; |
1855 |
+ rxcb->rtwdev = rtwusb->rtwdev; |
1856 |
+ rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); |
1857 |
+ if (!rxcb->rx_urb) |
1858 |
+ goto err; |
1859 |
+ } |
1860 |
+ |
1861 |
+ return 0; |
1862 |
+err: |
1863 |
+ rtw_usb_free_rx_bufs(rtwusb); |
1864 |
+ return -ENOMEM; |
1865 |
+} |
1866 |
+ |
1867 |
+static int rtw_usb_setup(struct rtw_dev *rtwdev) |
1868 |
+{ |
1869 |
+ /* empty function for rtw_hci_ops */ |
1870 |
+ return 0; |
1871 |
+} |
1872 |
+ |
1873 |
+static int rtw_usb_start(struct rtw_dev *rtwdev) |
1874 |
+{ |
1875 |
+ return 0; |
1876 |
+} |
1877 |
+ |
1878 |
+static void rtw_usb_stop(struct rtw_dev *rtwdev) |
1879 |
+{ |
1880 |
+} |
1881 |
+ |
1882 |
+static void rtw_usb_deep_ps(struct rtw_dev *rtwdev, bool enter) |
1883 |
+{ |
1884 |
+ /* empty function for rtw_hci_ops */ |
1885 |
+} |
1886 |
+ |
1887 |
+static void rtw_usb_link_ps(struct rtw_dev *rtwdev, bool enter) |
1888 |
+{ |
1889 |
+ /* empty function for rtw_hci_ops */ |
1890 |
+} |
1891 |
+ |
1892 |
+static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev) |
1893 |
+{ |
1894 |
+ /* empty function for rtw_hci_ops */ |
1895 |
+} |
1896 |
+ |
1897 |
+static struct rtw_hci_ops rtw_usb_ops = { |
1898 |
+ .tx_write = rtw_usb_tx_write, |
1899 |
+ .tx_kick_off = rtw_usb_tx_kick_off, |
1900 |
+ .setup = rtw_usb_setup, |
1901 |
+ .start = rtw_usb_start, |
1902 |
+ .stop = rtw_usb_stop, |
1903 |
+ .deep_ps = rtw_usb_deep_ps, |
1904 |
+ .link_ps = rtw_usb_link_ps, |
1905 |
+ .interface_cfg = rtw_usb_interface_cfg, |
1906 |
+ |
1907 |
+ .write8 = rtw_usb_write8, |
1908 |
+ .write16 = rtw_usb_write16, |
1909 |
+ .write32 = rtw_usb_write32, |
1910 |
+ .read8 = rtw_usb_read8, |
1911 |
+ .read16 = rtw_usb_read16, |
1912 |
+ .read32 = rtw_usb_read32, |
1913 |
+ |
1914 |
+ .write_data_rsvd_page = rtw_usb_write_data_rsvd_page, |
1915 |
+ .write_data_h2c = rtw_usb_write_data_h2c, |
1916 |
+}; |
1917 |
+ |
1918 |
+static int rtw_usb_init_rx(struct rtw_dev *rtwdev) |
1919 |
+{ |
1920 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1921 |
+ int i; |
1922 |
+ |
1923 |
+ rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq"); |
1924 |
+ if (!rtwusb->rxwq) { |
1925 |
+ rtw_err(rtwdev, "failed to create RX work queue\n"); |
1926 |
+ return -ENOMEM; |
1927 |
+ } |
1928 |
+ |
1929 |
+ skb_queue_head_init(&rtwusb->rx_queue); |
1930 |
+ |
1931 |
+ INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler); |
1932 |
+ |
1933 |
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) { |
1934 |
+ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; |
1935 |
+ |
1936 |
+ rtw_usb_rx_resubmit(rtwusb, rxcb); |
1937 |
+ } |
1938 |
+ |
1939 |
+ return 0; |
1940 |
+} |
1941 |
+ |
1942 |
+static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev) |
1943 |
+{ |
1944 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1945 |
+ |
1946 |
+ skb_queue_purge(&rtwusb->rx_queue); |
1947 |
+ |
1948 |
+ flush_workqueue(rtwusb->rxwq); |
1949 |
+ destroy_workqueue(rtwusb->rxwq); |
1950 |
+} |
1951 |
+ |
1952 |
+static int rtw_usb_init_tx(struct rtw_dev *rtwdev) |
1953 |
+{ |
1954 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1955 |
+ int i; |
1956 |
+ |
1957 |
+ rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq"); |
1958 |
+ if (!rtwusb->txwq) { |
1959 |
+ rtw_err(rtwdev, "failed to create TX work queue\n"); |
1960 |
+ return -ENOMEM; |
1961 |
+ } |
1962 |
+ |
1963 |
+ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) |
1964 |
+ skb_queue_head_init(&rtwusb->tx_queue[i]); |
1965 |
+ |
1966 |
+ INIT_WORK(&rtwusb->tx_work, rtw_usb_tx_handler); |
1967 |
+ |
1968 |
+ return 0; |
1969 |
+} |
1970 |
+ |
1971 |
+static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) |
1972 |
+{ |
1973 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1974 |
+ |
1975 |
+ rtw_usb_tx_queue_purge(rtwusb); |
1976 |
+ flush_workqueue(rtwusb->txwq); |
1977 |
+ destroy_workqueue(rtwusb->txwq); |
1978 |
+} |
1979 |
+ |
1980 |
+static int rtw_usb_intf_init(struct rtw_dev *rtwdev, |
1981 |
+ struct usb_interface *intf) |
1982 |
+{ |
1983 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
1984 |
+ struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf)); |
1985 |
+ int ret; |
1986 |
+ |
1987 |
+ rtwusb->udev = udev; |
1988 |
+ ret = rtw_usb_parse(rtwdev, intf); |
1989 |
+ if (ret) |
1990 |
+ return ret; |
1991 |
+ |
1992 |
+ rtwusb->usb_data = kcalloc(RTW_USB_MAX_RXTX_COUNT, sizeof(u32), |
1993 |
+ GFP_KERNEL); |
1994 |
+ if (!rtwusb->usb_data) |
1995 |
+ return -ENOMEM; |
1996 |
+ |
1997 |
+ usb_set_intfdata(intf, rtwdev->hw); |
1998 |
+ |
1999 |
+ SET_IEEE80211_DEV(rtwdev->hw, &intf->dev); |
2000 |
+ spin_lock_init(&rtwusb->usb_lock); |
2001 |
+ |
2002 |
+ return 0; |
2003 |
+} |
2004 |
+ |
2005 |
+static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev, |
2006 |
+ struct usb_interface *intf) |
2007 |
+{ |
2008 |
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); |
2009 |
+ |
2010 |
+ usb_put_dev(rtwusb->udev); |
2011 |
+ usb_set_intfdata(intf, NULL); |
2012 |
+} |
2013 |
+ |
2014 |
+int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) |
2015 |
+{ |
2016 |
+ struct rtw_dev *rtwdev; |
2017 |
+ struct ieee80211_hw *hw; |
2018 |
+ struct rtw_usb *rtwusb; |
2019 |
+ int drv_data_size; |
2020 |
+ int ret; |
2021 |
+ |
2022 |
+ drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_usb); |
2023 |
+ hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops); |
2024 |
+ if (!hw) |
2025 |
+ return -ENOMEM; |
2026 |
+ |
2027 |
+ rtwdev = hw->priv; |
2028 |
+ rtwdev->hw = hw; |
2029 |
+ rtwdev->dev = &intf->dev; |
2030 |
+ rtwdev->chip = (struct rtw_chip_info *)id->driver_info; |
2031 |
+ rtwdev->hci.ops = &rtw_usb_ops; |
2032 |
+ rtwdev->hci.type = RTW_HCI_TYPE_USB; |
2033 |
+ |
2034 |
+ rtwusb = rtw_get_usb_priv(rtwdev); |
2035 |
+ rtwusb->rtwdev = rtwdev; |
2036 |
+ |
2037 |
+ ret = rtw_usb_alloc_rx_bufs(rtwusb); |
2038 |
+ if (ret) |
2039 |
+ return ret; |
2040 |
+ |
2041 |
+ ret = rtw_core_init(rtwdev); |
2042 |
+ if (ret) |
2043 |
+ goto err_release_hw; |
2044 |
+ |
2045 |
+ ret = rtw_usb_intf_init(rtwdev, intf); |
2046 |
+ if (ret) { |
2047 |
+ rtw_err(rtwdev, "failed to init USB interface\n"); |
2048 |
+ goto err_deinit_core; |
2049 |
+ } |
2050 |
+ |
2051 |
+ ret = rtw_usb_init_tx(rtwdev); |
2052 |
+ if (ret) { |
2053 |
+ rtw_err(rtwdev, "failed to init USB TX\n"); |
2054 |
+ goto err_destroy_usb; |
2055 |
+ } |
2056 |
+ |
2057 |
+ ret = rtw_usb_init_rx(rtwdev); |
2058 |
+ if (ret) { |
2059 |
+ rtw_err(rtwdev, "failed to init USB RX\n"); |
2060 |
+ goto err_destroy_txwq; |
2061 |
+ } |
2062 |
+ |
2063 |
+ ret = rtw_chip_info_setup(rtwdev); |
2064 |
+ if (ret) { |
2065 |
+ rtw_err(rtwdev, "failed to setup chip information\n"); |
2066 |
+ goto err_destroy_rxwq; |
2067 |
+ } |
2068 |
+ |
2069 |
+ ret = rtw_register_hw(rtwdev, rtwdev->hw); |
2070 |
+ if (ret) { |
2071 |
+ rtw_err(rtwdev, "failed to register hw\n"); |
2072 |
+ goto err_destroy_rxwq; |
2073 |
+ } |
2074 |
+ |
2075 |
+ return 0; |
2076 |
+ |
2077 |
+err_destroy_rxwq: |
2078 |
+ rtw_usb_deinit_rx(rtwdev); |
2079 |
+ |
2080 |
+err_destroy_txwq: |
2081 |
+ rtw_usb_deinit_tx(rtwdev); |
2082 |
+ |
2083 |
+err_destroy_usb: |
2084 |
+ rtw_usb_intf_deinit(rtwdev, intf); |
2085 |
+ |
2086 |
+err_deinit_core: |
2087 |
+ rtw_core_deinit(rtwdev); |
2088 |
+ |
2089 |
+err_release_hw: |
2090 |
+ ieee80211_free_hw(hw); |
2091 |
+ |
2092 |
+ return ret; |
2093 |
+} |
2094 |
+EXPORT_SYMBOL(rtw_usb_probe); |
2095 |
+ |
2096 |
+void rtw_usb_disconnect(struct usb_interface *intf) |
2097 |
+{ |
2098 |
+ struct ieee80211_hw *hw = usb_get_intfdata(intf); |
2099 |
+ struct rtw_dev *rtwdev; |
2100 |
+ struct rtw_usb *rtwusb; |
2101 |
+ |
2102 |
+ if (!hw) |
2103 |
+ return; |
2104 |
+ |
2105 |
+ rtwdev = hw->priv; |
2106 |
+ rtwusb = rtw_get_usb_priv(rtwdev); |
2107 |
+ |
2108 |
+ rtw_usb_cancel_rx_bufs(rtwusb); |
2109 |
+ |
2110 |
+ rtw_unregister_hw(rtwdev, hw); |
2111 |
+ rtw_usb_deinit_tx(rtwdev); |
2112 |
+ rtw_usb_deinit_rx(rtwdev); |
2113 |
+ |
2114 |
+ if (rtwusb->udev->state != USB_STATE_NOTATTACHED) |
2115 |
+ usb_reset_device(rtwusb->udev); |
2116 |
+ |
2117 |
+ rtw_usb_free_rx_bufs(rtwusb); |
2118 |
+ |
2119 |
+ rtw_usb_intf_deinit(rtwdev, intf); |
2120 |
+ rtw_core_deinit(rtwdev); |
2121 |
+ ieee80211_free_hw(hw); |
2122 |
+} |
2123 |
+EXPORT_SYMBOL(rtw_usb_disconnect); |
2124 |
+ |
2125 |
+MODULE_AUTHOR("Realtek Corporation"); |
2126 |
+MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver"); |
2127 |
+MODULE_LICENSE("Dual BSD/GPL"); |
2128 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/usb.h linux-6.2/drivers/net/wireless/realtek/rtw88/usb.h |
2129 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/usb.h 1970-01-01 02:00:00.000000000 +0200 |
2130 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/usb.h 2022-12-24 00:49:25.775376835 +0200 |
2131 |
@@ -0,0 +1,107 @@ |
2132 |
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ |
2133 |
+/* Copyright(c) 2018-2019 Realtek Corporation |
2134 |
+ */ |
2135 |
+ |
2136 |
+#ifndef __RTW_USB_H_ |
2137 |
+#define __RTW_USB_H_ |
2138 |
+ |
2139 |
+#define FW_8192C_START_ADDRESS 0x1000 |
2140 |
+#define FW_8192C_END_ADDRESS 0x5fff |
2141 |
+ |
2142 |
+#define RTW_USB_MAX_RXTX_COUNT 128 |
2143 |
+#define RTW_USB_VENQT_MAX_BUF_SIZE 254 |
2144 |
+#define MAX_USBCTRL_VENDORREQ_TIMES 10 |
2145 |
+ |
2146 |
+#define RTW_USB_CMD_READ 0xc0 |
2147 |
+#define RTW_USB_CMD_WRITE 0x40 |
2148 |
+#define RTW_USB_CMD_REQ 0x05 |
2149 |
+ |
2150 |
+#define RTW_USB_VENQT_CMD_IDX 0x00 |
2151 |
+ |
2152 |
+#define RTW_USB_SUPER_SPEED_BULK_SIZE 1024 |
2153 |
+#define RTW_USB_HIGH_SPEED_BULK_SIZE 512 |
2154 |
+#define RTW_USB_FULL_SPEED_BULK_SIZE 64 |
2155 |
+ |
2156 |
+#define RTW_USB_TX_SEL_HQ BIT(0) |
2157 |
+#define RTW_USB_TX_SEL_LQ BIT(1) |
2158 |
+#define RTW_USB_TX_SEL_NQ BIT(2) |
2159 |
+#define RTW_USB_TX_SEL_EQ BIT(3) |
2160 |
+ |
2161 |
+#define RTW_USB_BULK_IN_ADDR 0x80 |
2162 |
+#define RTW_USB_INT_IN_ADDR 0x81 |
2163 |
+ |
2164 |
+#define RTW_USB_HW_QUEUE_ENTRY 8 |
2165 |
+ |
2166 |
+#define RTW_USB_PACKET_OFFSET_SZ 8 |
2167 |
+#define RTW_USB_MAX_XMITBUF_SZ (1024 * 20) |
2168 |
+#define RTW_USB_MAX_RECVBUF_SZ 32768 |
2169 |
+ |
2170 |
+#define RTW_USB_RECVBUFF_ALIGN_SZ 8 |
2171 |
+ |
2172 |
+#define RTW_USB_RXAGG_SIZE 6 |
2173 |
+#define RTW_USB_RXAGG_TIMEOUT 10 |
2174 |
+ |
2175 |
+#define RTW_USB_RXCB_NUM 4 |
2176 |
+ |
2177 |
+#define RTW_USB_EP_MAX 4 |
2178 |
+ |
2179 |
+#define TX_DESC_QSEL_MAX 20 |
2180 |
+ |
2181 |
+#define RTW_USB_VENDOR_ID_REALTEK 0x0bda |
2182 |
+ |
2183 |
+static inline struct rtw_usb *rtw_get_usb_priv(struct rtw_dev *rtwdev) |
2184 |
+{ |
2185 |
+ return (struct rtw_usb *)rtwdev->priv; |
2186 |
+} |
2187 |
+ |
2188 |
+struct rx_usb_ctrl_block { |
2189 |
+ struct rtw_dev *rtwdev; |
2190 |
+ struct urb *rx_urb; |
2191 |
+ struct sk_buff *rx_skb; |
2192 |
+ int n; |
2193 |
+}; |
2194 |
+ |
2195 |
+struct rtw_usb_tx_data { |
2196 |
+ u8 sn; |
2197 |
+}; |
2198 |
+ |
2199 |
+struct rtw_usb { |
2200 |
+ struct rtw_dev *rtwdev; |
2201 |
+ struct usb_device *udev; |
2202 |
+ |
2203 |
+ /* protects usb_data_index */ |
2204 |
+ spinlock_t usb_lock; |
2205 |
+ __le32 *usb_data; |
2206 |
+ unsigned int usb_data_index; |
2207 |
+ |
2208 |
+ u32 bulkout_size; |
2209 |
+ u8 pipe_interrupt; |
2210 |
+ u8 pipe_in; |
2211 |
+ u8 out_ep[RTW_USB_EP_MAX]; |
2212 |
+ u8 qsel_to_ep[TX_DESC_QSEL_MAX]; |
2213 |
+ u8 usb_txagg_num; |
2214 |
+ |
2215 |
+ struct workqueue_struct *txwq, *rxwq; |
2216 |
+ |
2217 |
+ struct sk_buff_head tx_queue[RTW_USB_EP_MAX]; |
2218 |
+ struct work_struct tx_work; |
2219 |
+ |
2220 |
+ struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM]; |
2221 |
+ struct sk_buff_head rx_queue; |
2222 |
+ struct work_struct rx_work; |
2223 |
+}; |
2224 |
+ |
2225 |
+static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb) |
2226 |
+{ |
2227 |
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2228 |
+ |
2229 |
+ BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) > |
2230 |
+ sizeof(info->status.status_driver_data)); |
2231 |
+ |
2232 |
+ return (struct rtw_usb_tx_data *)info->status.status_driver_data; |
2233 |
+} |
2234 |
+ |
2235 |
+int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id); |
2236 |
+void rtw_usb_disconnect(struct usb_interface *intf); |
2237 |
+ |
2238 |
+#endif |
2239 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/util.c linux-6.2/drivers/net/wireless/realtek/rtw88/util.c |
2240 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/util.c 2022-12-12 00:15:18.000000000 +0200 |
2241 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/util.c 2022-12-24 00:49:25.775376835 +0200 |
2242 |
@@ -105,3 +105,106 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *m |
2243 |
*mcs = rate - DESC_RATEMCS0; |
2244 |
} |
2245 |
} |
2246 |
+ |
2247 |
+struct rtw_stas_entry { |
2248 |
+ struct list_head list; |
2249 |
+ struct ieee80211_sta *sta; |
2250 |
+}; |
2251 |
+ |
2252 |
+struct rtw_iter_stas_data { |
2253 |
+ struct rtw_dev *rtwdev; |
2254 |
+ struct list_head list; |
2255 |
+}; |
2256 |
+ |
2257 |
+static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta) |
2258 |
+{ |
2259 |
+ struct rtw_iter_stas_data *iter_stas = data; |
2260 |
+ struct rtw_stas_entry *stas_entry; |
2261 |
+ |
2262 |
+ stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC); |
2263 |
+ if (!stas_entry) |
2264 |
+ return; |
2265 |
+ |
2266 |
+ stas_entry->sta = sta; |
2267 |
+ list_add_tail(&stas_entry->list, &iter_stas->list); |
2268 |
+} |
2269 |
+ |
2270 |
+void rtw_iterate_stas(struct rtw_dev *rtwdev, |
2271 |
+ void (*iterator)(void *data, |
2272 |
+ struct ieee80211_sta *sta), |
2273 |
+ void *data) |
2274 |
+{ |
2275 |
+ struct rtw_iter_stas_data iter_data; |
2276 |
+ struct rtw_stas_entry *sta_entry, *tmp; |
2277 |
+ |
2278 |
+ /* &rtwdev->mutex makes sure no stations can be removed between |
2279 |
+ * collecting the stations and iterating over them. |
2280 |
+ */ |
2281 |
+ lockdep_assert_held(&rtwdev->mutex); |
2282 |
+ |
2283 |
+ iter_data.rtwdev = rtwdev; |
2284 |
+ INIT_LIST_HEAD(&iter_data.list); |
2285 |
+ |
2286 |
+ ieee80211_iterate_stations_atomic(rtwdev->hw, rtw_collect_sta_iter, |
2287 |
+ &iter_data); |
2288 |
+ |
2289 |
+ list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, |
2290 |
+ list) { |
2291 |
+ list_del_init(&sta_entry->list); |
2292 |
+ iterator(data, sta_entry->sta); |
2293 |
+ kfree(sta_entry); |
2294 |
+ } |
2295 |
+} |
2296 |
+ |
2297 |
+struct rtw_vifs_entry { |
2298 |
+ struct list_head list; |
2299 |
+ struct ieee80211_vif *vif; |
2300 |
+ u8 mac[ETH_ALEN]; |
2301 |
+}; |
2302 |
+ |
2303 |
+struct rtw_iter_vifs_data { |
2304 |
+ struct rtw_dev *rtwdev; |
2305 |
+ struct list_head list; |
2306 |
+}; |
2307 |
+ |
2308 |
+static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
2309 |
+{ |
2310 |
+ struct rtw_iter_vifs_data *iter_stas = data; |
2311 |
+ struct rtw_vifs_entry *vifs_entry; |
2312 |
+ |
2313 |
+ vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC); |
2314 |
+ if (!vifs_entry) |
2315 |
+ return; |
2316 |
+ |
2317 |
+ vifs_entry->vif = vif; |
2318 |
+ ether_addr_copy(vifs_entry->mac, mac); |
2319 |
+ list_add_tail(&vifs_entry->list, &iter_stas->list); |
2320 |
+} |
2321 |
+ |
2322 |
+void rtw_iterate_vifs(struct rtw_dev *rtwdev, |
2323 |
+ void (*iterator)(void *data, u8 *mac, |
2324 |
+ struct ieee80211_vif *vif), |
2325 |
+ void *data) |
2326 |
+{ |
2327 |
+ struct rtw_iter_vifs_data iter_data; |
2328 |
+ struct rtw_vifs_entry *vif_entry, *tmp; |
2329 |
+ |
2330 |
+ /* &rtwdev->mutex makes sure no interfaces can be removed between |
2331 |
+ * collecting the interfaces and iterating over them. |
2332 |
+ */ |
2333 |
+ lockdep_assert_held(&rtwdev->mutex); |
2334 |
+ |
2335 |
+ iter_data.rtwdev = rtwdev; |
2336 |
+ INIT_LIST_HEAD(&iter_data.list); |
2337 |
+ |
2338 |
+ ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, |
2339 |
+ IEEE80211_IFACE_ITER_NORMAL, |
2340 |
+ rtw_collect_vif_iter, &iter_data); |
2341 |
+ |
2342 |
+ list_for_each_entry_safe(vif_entry, tmp, &iter_data.list, |
2343 |
+ list) { |
2344 |
+ list_del_init(&vif_entry->list); |
2345 |
+ iterator(data, vif_entry->mac, vif_entry->vif); |
2346 |
+ kfree(vif_entry); |
2347 |
+ } |
2348 |
+} |
2349 |
diff -Nurp linux-6.1/drivers/net/wireless/realtek/rtw88/util.h linux-6.2/drivers/net/wireless/realtek/rtw88/util.h |
2350 |
--- linux-6.1/drivers/net/wireless/realtek/rtw88/util.h 2022-12-12 00:15:18.000000000 +0200 |
2351 |
+++ linux-6.2/drivers/net/wireless/realtek/rtw88/util.h 2022-12-24 00:49:25.775376835 +0200 |
2352 |
@@ -7,9 +7,6 @@ |
2353 |
|
2354 |
struct rtw_dev; |
2355 |
|
2356 |
-#define rtw_iterate_vifs(rtwdev, iterator, data) \ |
2357 |
- ieee80211_iterate_active_interfaces(rtwdev->hw, \ |
2358 |
- IEEE80211_IFACE_ITER_NORMAL, iterator, data) |
2359 |
#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \ |
2360 |
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \ |
2361 |
IEEE80211_IFACE_ITER_NORMAL, iterator, data) |
2362 |
@@ -20,6 +17,15 @@ struct rtw_dev; |
2363 |
#define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \ |
2364 |
ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) |
2365 |
|
2366 |
+void rtw_iterate_vifs(struct rtw_dev *rtwdev, |
2367 |
+ void (*iterator)(void *data, u8 *mac, |
2368 |
+ struct ieee80211_vif *vif), |
2369 |
+ void *data); |
2370 |
+void rtw_iterate_stas(struct rtw_dev *rtwdev, |
2371 |
+ void (*iterator)(void *data, |
2372 |
+ struct ieee80211_sta *sta), |
2373 |
+ void *data); |
2374 |
+ |
2375 |
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) |
2376 |
{ |
2377 |
__le16 fc = hdr->frame_control; |