1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * RTL8XXXU mac80211 USB driver |
4 | * |
5 | * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> |
6 | * |
7 | * Portions, notably calibration code: |
8 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. |
9 | * |
10 | * This driver was written as a replacement for the vendor provided |
11 | * rtl8723au driver. As the Realtek 8xxx chips are very similar in |
12 | * their programming interface, I have started adding support for |
13 | * additional 8xxx chips like the 8192cu, 8188cus, etc. |
14 | */ |
15 | |
16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/sched.h> |
19 | #include <linux/errno.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/module.h> |
22 | #include <linux/spinlock.h> |
23 | #include <linux/list.h> |
24 | #include <linux/usb.h> |
25 | #include <linux/netdevice.h> |
26 | #include <linux/etherdevice.h> |
27 | #include <linux/ethtool.h> |
28 | #include <linux/wireless.h> |
29 | #include <linux/firmware.h> |
30 | #include <linux/moduleparam.h> |
31 | #include <net/mac80211.h> |
32 | #include "rtl8xxxu.h" |
33 | #include "rtl8xxxu_regs.h" |
34 | |
35 | #define DRIVER_NAME "rtl8xxxu" |
36 | |
37 | int rtl8xxxu_debug; |
38 | static bool rtl8xxxu_ht40_2g; |
39 | static bool rtl8xxxu_dma_aggregation; |
40 | static int rtl8xxxu_dma_agg_timeout = -1; |
41 | static int rtl8xxxu_dma_agg_pages = -1; |
42 | |
43 | MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>" ); |
44 | MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver" ); |
45 | MODULE_LICENSE("GPL" ); |
46 | MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin" ); |
47 | MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin" ); |
48 | MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin" ); |
49 | MODULE_FIRMWARE("rtlwifi/rtl8188eufw.bin" ); |
50 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin" ); |
51 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin" ); |
52 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin" ); |
53 | MODULE_FIRMWARE("rtlwifi/rtl8192eu_nic.bin" ); |
54 | MODULE_FIRMWARE("rtlwifi/rtl8723bu_nic.bin" ); |
55 | MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin" ); |
56 | MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin" ); |
57 | MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin" ); |
58 | MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin" ); |
59 | MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin" ); |
60 | |
61 | module_param_named(debug, rtl8xxxu_debug, int, 0600); |
62 | MODULE_PARM_DESC(debug, "Set debug mask" ); |
63 | module_param_named(ht40_2g, rtl8xxxu_ht40_2g, bool, 0600); |
64 | MODULE_PARM_DESC(ht40_2g, "Enable HT40 support on the 2.4GHz band" ); |
65 | module_param_named(dma_aggregation, rtl8xxxu_dma_aggregation, bool, 0600); |
66 | MODULE_PARM_DESC(dma_aggregation, "Enable DMA packet aggregation" ); |
67 | module_param_named(dma_agg_timeout, rtl8xxxu_dma_agg_timeout, int, 0600); |
68 | MODULE_PARM_DESC(dma_agg_timeout, "Set DMA aggregation timeout (range 1-127)" ); |
69 | module_param_named(dma_agg_pages, rtl8xxxu_dma_agg_pages, int, 0600); |
70 | MODULE_PARM_DESC(dma_agg_pages, "Set DMA aggregation pages (range 1-127, 0 to disable)" ); |
71 | |
72 | #define USB_VENDOR_ID_REALTEK 0x0bda |
73 | #define RTL8XXXU_RX_URBS 32 |
74 | #define RTL8XXXU_RX_URB_PENDING_WATER 8 |
75 | #define RTL8XXXU_TX_URBS 64 |
76 | #define RTL8XXXU_TX_URB_LOW_WATER 25 |
77 | #define RTL8XXXU_TX_URB_HIGH_WATER 32 |
78 | |
79 | static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, |
80 | struct rtl8xxxu_rx_urb *rx_urb); |
81 | |
82 | static struct ieee80211_rate rtl8xxxu_rates[] = { |
83 | { .bitrate = 10, .hw_value = DESC_RATE_1M, .flags = 0 }, |
84 | { .bitrate = 20, .hw_value = DESC_RATE_2M, .flags = 0 }, |
85 | { .bitrate = 55, .hw_value = DESC_RATE_5_5M, .flags = 0 }, |
86 | { .bitrate = 110, .hw_value = DESC_RATE_11M, .flags = 0 }, |
87 | { .bitrate = 60, .hw_value = DESC_RATE_6M, .flags = 0 }, |
88 | { .bitrate = 90, .hw_value = DESC_RATE_9M, .flags = 0 }, |
89 | { .bitrate = 120, .hw_value = DESC_RATE_12M, .flags = 0 }, |
90 | { .bitrate = 180, .hw_value = DESC_RATE_18M, .flags = 0 }, |
91 | { .bitrate = 240, .hw_value = DESC_RATE_24M, .flags = 0 }, |
92 | { .bitrate = 360, .hw_value = DESC_RATE_36M, .flags = 0 }, |
93 | { .bitrate = 480, .hw_value = DESC_RATE_48M, .flags = 0 }, |
94 | { .bitrate = 540, .hw_value = DESC_RATE_54M, .flags = 0 }, |
95 | }; |
96 | |
97 | static struct ieee80211_channel rtl8xxxu_channels_2g[] = { |
98 | { .band = NL80211_BAND_2GHZ, .center_freq = 2412, |
99 | .hw_value = 1, .max_power = 30 }, |
100 | { .band = NL80211_BAND_2GHZ, .center_freq = 2417, |
101 | .hw_value = 2, .max_power = 30 }, |
102 | { .band = NL80211_BAND_2GHZ, .center_freq = 2422, |
103 | .hw_value = 3, .max_power = 30 }, |
104 | { .band = NL80211_BAND_2GHZ, .center_freq = 2427, |
105 | .hw_value = 4, .max_power = 30 }, |
106 | { .band = NL80211_BAND_2GHZ, .center_freq = 2432, |
107 | .hw_value = 5, .max_power = 30 }, |
108 | { .band = NL80211_BAND_2GHZ, .center_freq = 2437, |
109 | .hw_value = 6, .max_power = 30 }, |
110 | { .band = NL80211_BAND_2GHZ, .center_freq = 2442, |
111 | .hw_value = 7, .max_power = 30 }, |
112 | { .band = NL80211_BAND_2GHZ, .center_freq = 2447, |
113 | .hw_value = 8, .max_power = 30 }, |
114 | { .band = NL80211_BAND_2GHZ, .center_freq = 2452, |
115 | .hw_value = 9, .max_power = 30 }, |
116 | { .band = NL80211_BAND_2GHZ, .center_freq = 2457, |
117 | .hw_value = 10, .max_power = 30 }, |
118 | { .band = NL80211_BAND_2GHZ, .center_freq = 2462, |
119 | .hw_value = 11, .max_power = 30 }, |
120 | { .band = NL80211_BAND_2GHZ, .center_freq = 2467, |
121 | .hw_value = 12, .max_power = 30 }, |
122 | { .band = NL80211_BAND_2GHZ, .center_freq = 2472, |
123 | .hw_value = 13, .max_power = 30 }, |
124 | { .band = NL80211_BAND_2GHZ, .center_freq = 2484, |
125 | .hw_value = 14, .max_power = 30 } |
126 | }; |
127 | |
128 | static struct ieee80211_supported_band rtl8xxxu_supported_band = { |
129 | .channels = rtl8xxxu_channels_2g, |
130 | .n_channels = ARRAY_SIZE(rtl8xxxu_channels_2g), |
131 | .bitrates = rtl8xxxu_rates, |
132 | .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates), |
133 | }; |
134 | |
135 | const struct rtl8xxxu_reg8val rtl8xxxu_gen1_mac_init_table[] = { |
136 | {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00}, |
137 | {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, |
138 | {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00}, |
139 | {0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05}, |
140 | {0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01}, |
141 | {0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f}, |
142 | {0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72}, |
143 | {0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08}, |
144 | {0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, |
145 | {0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, |
146 | {0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, |
147 | {0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, |
148 | {0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, |
149 | {0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, |
150 | {0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16}, |
151 | {0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00}, |
152 | {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02}, |
153 | {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, |
154 | {0x652, 0x20}, {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, |
155 | {0x63f, 0x0e}, {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, |
156 | {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, |
157 | {0x70a, 0x65}, {0x70b, 0x87}, {0xffff, 0xff}, |
158 | }; |
159 | |
160 | static const struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { |
161 | {0x800, 0x80040000}, {0x804, 0x00000003}, |
162 | {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, |
163 | {0x810, 0x10001331}, {0x814, 0x020c3d10}, |
164 | {0x818, 0x02200385}, {0x81c, 0x00000000}, |
165 | {0x820, 0x01000100}, {0x824, 0x00390004}, |
166 | {0x828, 0x00000000}, {0x82c, 0x00000000}, |
167 | {0x830, 0x00000000}, {0x834, 0x00000000}, |
168 | {0x838, 0x00000000}, {0x83c, 0x00000000}, |
169 | {0x840, 0x00010000}, {0x844, 0x00000000}, |
170 | {0x848, 0x00000000}, {0x84c, 0x00000000}, |
171 | {0x850, 0x00000000}, {0x854, 0x00000000}, |
172 | {0x858, 0x569a569a}, {0x85c, 0x001b25a4}, |
173 | {0x860, 0x66f60110}, {0x864, 0x061f0130}, |
174 | {0x868, 0x00000000}, {0x86c, 0x32323200}, |
175 | {0x870, 0x07000760}, {0x874, 0x22004000}, |
176 | {0x878, 0x00000808}, {0x87c, 0x00000000}, |
177 | {0x880, 0xc0083070}, {0x884, 0x000004d5}, |
178 | {0x888, 0x00000000}, {0x88c, 0xccc000c0}, |
179 | {0x890, 0x00000800}, {0x894, 0xfffffffe}, |
180 | {0x898, 0x40302010}, {0x89c, 0x00706050}, |
181 | {0x900, 0x00000000}, {0x904, 0x00000023}, |
182 | {0x908, 0x00000000}, {0x90c, 0x81121111}, |
183 | {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, |
184 | {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, |
185 | {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, |
186 | {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, |
187 | {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, |
188 | {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, |
189 | {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, |
190 | {0xa78, 0x00000900}, |
191 | {0xc00, 0x48071d40}, {0xc04, 0x03a05611}, |
192 | {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, |
193 | {0xc10, 0x08800000}, {0xc14, 0x40000100}, |
194 | {0xc18, 0x08800000}, {0xc1c, 0x40000100}, |
195 | {0xc20, 0x00000000}, {0xc24, 0x00000000}, |
196 | {0xc28, 0x00000000}, {0xc2c, 0x00000000}, |
197 | {0xc30, 0x69e9ac44}, {0xc34, 0x469652af}, |
198 | {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, |
199 | {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, |
200 | {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, |
201 | {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, |
202 | {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, |
203 | {0xc60, 0x00000000}, {0xc64, 0x7112848b}, |
204 | {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, |
205 | {0xc70, 0x2c7f000d}, {0xc74, 0x018610db}, |
206 | {0xc78, 0x0000001f}, {0xc7c, 0x00b91612}, |
207 | {0xc80, 0x40000100}, {0xc84, 0x20f60000}, |
208 | {0xc88, 0x40000100}, {0xc8c, 0x20200000}, |
209 | {0xc90, 0x00121820}, {0xc94, 0x00000000}, |
210 | {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, |
211 | {0xca0, 0x00000000}, {0xca4, 0x00000080}, |
212 | {0xca8, 0x00000000}, {0xcac, 0x00000000}, |
213 | {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, |
214 | {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, |
215 | {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, |
216 | {0xcc8, 0x00000000}, {0xccc, 0x00000000}, |
217 | {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, |
218 | {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, |
219 | {0xce0, 0x00222222}, {0xce4, 0x00000000}, |
220 | {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, |
221 | {0xd00, 0x00080740}, {0xd04, 0x00020401}, |
222 | {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, |
223 | {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, |
224 | {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, |
225 | {0xd30, 0x00000000}, {0xd34, 0x80608000}, |
226 | {0xd38, 0x00000000}, {0xd3c, 0x00027293}, |
227 | {0xd40, 0x00000000}, {0xd44, 0x00000000}, |
228 | {0xd48, 0x00000000}, {0xd4c, 0x00000000}, |
229 | {0xd50, 0x6437140a}, {0xd54, 0x00000000}, |
230 | {0xd58, 0x00000000}, {0xd5c, 0x30032064}, |
231 | {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, |
232 | {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, |
233 | {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, |
234 | {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, |
235 | {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, |
236 | {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, |
237 | {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, |
238 | {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, |
239 | {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, |
240 | {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, |
241 | {0xe44, 0x01004800}, {0xe48, 0xfb000000}, |
242 | {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, |
243 | {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, |
244 | {0xe5c, 0x28160d05}, {0xe60, 0x00000008}, |
245 | {0xe68, 0x001b25a4}, {0xe6c, 0x631b25a0}, |
246 | {0xe70, 0x631b25a0}, {0xe74, 0x081b25a0}, |
247 | {0xe78, 0x081b25a0}, {0xe7c, 0x081b25a0}, |
248 | {0xe80, 0x081b25a0}, {0xe84, 0x631b25a0}, |
249 | {0xe88, 0x081b25a0}, {0xe8c, 0x631b25a0}, |
250 | {0xed0, 0x631b25a0}, {0xed4, 0x631b25a0}, |
251 | {0xed8, 0x631b25a0}, {0xedc, 0x001b25a0}, |
252 | {0xee0, 0x001b25a0}, {0xeec, 0x6b1b25a0}, |
253 | {0xf14, 0x00000003}, {0xf4c, 0x00000000}, |
254 | {0xf00, 0x00000300}, |
255 | {0xffff, 0xffffffff}, |
256 | }; |
257 | |
258 | static const struct rtl8xxxu_reg32val rtl8192cu_phy_2t_init_table[] = { |
259 | {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, |
260 | {0x800, 0x80040002}, {0x804, 0x00000003}, |
261 | {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, |
262 | {0x810, 0x10000330}, {0x814, 0x020c3d10}, |
263 | {0x818, 0x02200385}, {0x81c, 0x00000000}, |
264 | {0x820, 0x01000100}, {0x824, 0x00390004}, |
265 | {0x828, 0x01000100}, {0x82c, 0x00390004}, |
266 | {0x830, 0x27272727}, {0x834, 0x27272727}, |
267 | {0x838, 0x27272727}, {0x83c, 0x27272727}, |
268 | {0x840, 0x00010000}, {0x844, 0x00010000}, |
269 | {0x848, 0x27272727}, {0x84c, 0x27272727}, |
270 | {0x850, 0x00000000}, {0x854, 0x00000000}, |
271 | {0x858, 0x569a569a}, {0x85c, 0x0c1b25a4}, |
272 | {0x860, 0x66e60230}, {0x864, 0x061f0130}, |
273 | {0x868, 0x27272727}, {0x86c, 0x2b2b2b27}, |
274 | {0x870, 0x07000700}, {0x874, 0x22184000}, |
275 | {0x878, 0x08080808}, {0x87c, 0x00000000}, |
276 | {0x880, 0xc0083070}, {0x884, 0x000004d5}, |
277 | {0x888, 0x00000000}, {0x88c, 0xcc0000c0}, |
278 | {0x890, 0x00000800}, {0x894, 0xfffffffe}, |
279 | {0x898, 0x40302010}, {0x89c, 0x00706050}, |
280 | {0x900, 0x00000000}, {0x904, 0x00000023}, |
281 | {0x908, 0x00000000}, {0x90c, 0x81121313}, |
282 | {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, |
283 | {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, |
284 | {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, |
285 | {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, |
286 | {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, |
287 | {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, |
288 | {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, |
289 | {0xc00, 0x48071d40}, {0xc04, 0x03a05633}, |
290 | {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, |
291 | {0xc10, 0x08800000}, {0xc14, 0x40000100}, |
292 | {0xc18, 0x08800000}, {0xc1c, 0x40000100}, |
293 | {0xc20, 0x00000000}, {0xc24, 0x00000000}, |
294 | {0xc28, 0x00000000}, {0xc2c, 0x00000000}, |
295 | {0xc30, 0x69e9ac44}, {0xc34, 0x469652cf}, |
296 | {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, |
297 | {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, |
298 | {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, |
299 | {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, |
300 | {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, |
301 | {0xc60, 0x00000000}, {0xc64, 0x5116848b}, |
302 | {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, |
303 | {0xc70, 0x2c7f000d}, {0xc74, 0x2186115b}, |
304 | {0xc78, 0x0000001f}, {0xc7c, 0x00b99612}, |
305 | {0xc80, 0x40000100}, {0xc84, 0x20f60000}, |
306 | {0xc88, 0x40000100}, {0xc8c, 0xa0e40000}, |
307 | {0xc90, 0x00121820}, {0xc94, 0x00000000}, |
308 | {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, |
309 | {0xca0, 0x00000000}, {0xca4, 0x00000080}, |
310 | {0xca8, 0x00000000}, {0xcac, 0x00000000}, |
311 | {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, |
312 | {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, |
313 | {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, |
314 | {0xcc8, 0x00000000}, {0xccc, 0x00000000}, |
315 | {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, |
316 | {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, |
317 | {0xce0, 0x00222222}, {0xce4, 0x00000000}, |
318 | {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, |
319 | {0xd00, 0x00080740}, {0xd04, 0x00020403}, |
320 | {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, |
321 | {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, |
322 | {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, |
323 | {0xd30, 0x00000000}, {0xd34, 0x80608000}, |
324 | {0xd38, 0x00000000}, {0xd3c, 0x00027293}, |
325 | {0xd40, 0x00000000}, {0xd44, 0x00000000}, |
326 | {0xd48, 0x00000000}, {0xd4c, 0x00000000}, |
327 | {0xd50, 0x6437140a}, {0xd54, 0x00000000}, |
328 | {0xd58, 0x00000000}, {0xd5c, 0x30032064}, |
329 | {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, |
330 | {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, |
331 | {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, |
332 | {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, |
333 | {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, |
334 | {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, |
335 | {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, |
336 | {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, |
337 | {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, |
338 | {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, |
339 | {0xe44, 0x01004800}, {0xe48, 0xfb000000}, |
340 | {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, |
341 | {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, |
342 | {0xe5c, 0x28160d05}, {0xe60, 0x00000010}, |
343 | {0xe68, 0x001b25a4}, {0xe6c, 0x63db25a4}, |
344 | {0xe70, 0x63db25a4}, {0xe74, 0x0c1b25a4}, |
345 | {0xe78, 0x0c1b25a4}, {0xe7c, 0x0c1b25a4}, |
346 | {0xe80, 0x0c1b25a4}, {0xe84, 0x63db25a4}, |
347 | {0xe88, 0x0c1b25a4}, {0xe8c, 0x63db25a4}, |
348 | {0xed0, 0x63db25a4}, {0xed4, 0x63db25a4}, |
349 | {0xed8, 0x63db25a4}, {0xedc, 0x001b25a4}, |
350 | {0xee0, 0x001b25a4}, {0xeec, 0x6fdb25a4}, |
351 | {0xf14, 0x00000003}, {0xf4c, 0x00000000}, |
352 | {0xf00, 0x00000300}, |
353 | {0xffff, 0xffffffff}, |
354 | }; |
355 | |
356 | static const struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = { |
357 | {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, |
358 | {0x040, 0x000c0004}, {0x800, 0x80040000}, |
359 | {0x804, 0x00000001}, {0x808, 0x0000fc00}, |
360 | {0x80c, 0x0000000a}, {0x810, 0x10005388}, |
361 | {0x814, 0x020c3d10}, {0x818, 0x02200385}, |
362 | {0x81c, 0x00000000}, {0x820, 0x01000100}, |
363 | {0x824, 0x00390204}, {0x828, 0x00000000}, |
364 | {0x82c, 0x00000000}, {0x830, 0x00000000}, |
365 | {0x834, 0x00000000}, {0x838, 0x00000000}, |
366 | {0x83c, 0x00000000}, {0x840, 0x00010000}, |
367 | {0x844, 0x00000000}, {0x848, 0x00000000}, |
368 | {0x84c, 0x00000000}, {0x850, 0x00000000}, |
369 | {0x854, 0x00000000}, {0x858, 0x569a569a}, |
370 | {0x85c, 0x001b25a4}, {0x860, 0x66e60230}, |
371 | {0x864, 0x061f0130}, {0x868, 0x00000000}, |
372 | {0x86c, 0x20202000}, {0x870, 0x03000300}, |
373 | {0x874, 0x22004000}, {0x878, 0x00000808}, |
374 | {0x87c, 0x00ffc3f1}, {0x880, 0xc0083070}, |
375 | {0x884, 0x000004d5}, {0x888, 0x00000000}, |
376 | {0x88c, 0xccc000c0}, {0x890, 0x00000800}, |
377 | {0x894, 0xfffffffe}, {0x898, 0x40302010}, |
378 | {0x89c, 0x00706050}, {0x900, 0x00000000}, |
379 | {0x904, 0x00000023}, {0x908, 0x00000000}, |
380 | {0x90c, 0x81121111}, {0xa00, 0x00d047c8}, |
381 | {0xa04, 0x80ff000c}, {0xa08, 0x8c838300}, |
382 | {0xa0c, 0x2e68120f}, {0xa10, 0x9500bb78}, |
383 | {0xa14, 0x11144028}, {0xa18, 0x00881117}, |
384 | {0xa1c, 0x89140f00}, {0xa20, 0x15160000}, |
385 | {0xa24, 0x070b0f12}, {0xa28, 0x00000104}, |
386 | {0xa2c, 0x00d30000}, {0xa70, 0x101fbf00}, |
387 | {0xa74, 0x00000007}, {0xc00, 0x48071d40}, |
388 | {0xc04, 0x03a05611}, {0xc08, 0x000000e4}, |
389 | {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000}, |
390 | {0xc14, 0x40000100}, {0xc18, 0x08800000}, |
391 | {0xc1c, 0x40000100}, {0xc20, 0x00000000}, |
392 | {0xc24, 0x00000000}, {0xc28, 0x00000000}, |
393 | {0xc2c, 0x00000000}, {0xc30, 0x69e9ac44}, |
394 | {0xc34, 0x469652cf}, {0xc38, 0x49795994}, |
395 | {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f}, |
396 | {0xc44, 0x000100b7}, {0xc48, 0xec020107}, |
397 | {0xc4c, 0x007f037f}, {0xc50, 0x6954342e}, |
398 | {0xc54, 0x43bc0094}, {0xc58, 0x6954342f}, |
399 | {0xc5c, 0x433c0094}, {0xc60, 0x00000000}, |
400 | {0xc64, 0x5116848b}, {0xc68, 0x47c00bff}, |
401 | {0xc6c, 0x00000036}, {0xc70, 0x2c46000d}, |
402 | {0xc74, 0x018610db}, {0xc78, 0x0000001f}, |
403 | {0xc7c, 0x00b91612}, {0xc80, 0x24000090}, |
404 | {0xc84, 0x20f60000}, {0xc88, 0x24000090}, |
405 | {0xc8c, 0x20200000}, {0xc90, 0x00121820}, |
406 | {0xc94, 0x00000000}, {0xc98, 0x00121820}, |
407 | {0xc9c, 0x00007f7f}, {0xca0, 0x00000000}, |
408 | {0xca4, 0x00000080}, {0xca8, 0x00000000}, |
409 | {0xcac, 0x00000000}, {0xcb0, 0x00000000}, |
410 | {0xcb4, 0x00000000}, {0xcb8, 0x00000000}, |
411 | {0xcbc, 0x28000000}, {0xcc0, 0x00000000}, |
412 | {0xcc4, 0x00000000}, {0xcc8, 0x00000000}, |
413 | {0xccc, 0x00000000}, {0xcd0, 0x00000000}, |
414 | {0xcd4, 0x00000000}, {0xcd8, 0x64b22427}, |
415 | {0xcdc, 0x00766932}, {0xce0, 0x00222222}, |
416 | {0xce4, 0x00000000}, {0xce8, 0x37644302}, |
417 | {0xcec, 0x2f97d40c}, {0xd00, 0x00080740}, |
418 | {0xd04, 0x00020401}, {0xd08, 0x0000907f}, |
419 | {0xd0c, 0x20010201}, {0xd10, 0xa0633333}, |
420 | {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b}, |
421 | {0xd2c, 0xcc979975}, {0xd30, 0x00000000}, |
422 | {0xd34, 0x80608000}, {0xd38, 0x00000000}, |
423 | {0xd3c, 0x00027293}, {0xd40, 0x00000000}, |
424 | {0xd44, 0x00000000}, {0xd48, 0x00000000}, |
425 | {0xd4c, 0x00000000}, {0xd50, 0x6437140a}, |
426 | {0xd54, 0x00000000}, {0xd58, 0x00000000}, |
427 | {0xd5c, 0x30032064}, {0xd60, 0x4653de68}, |
428 | {0xd64, 0x04518a3c}, {0xd68, 0x00002101}, |
429 | {0xd6c, 0x2a201c16}, {0xd70, 0x1812362e}, |
430 | {0xd74, 0x322c2220}, {0xd78, 0x000e3c24}, |
431 | {0xe00, 0x24242424}, {0xe04, 0x24242424}, |
432 | {0xe08, 0x03902024}, {0xe10, 0x24242424}, |
433 | {0xe14, 0x24242424}, {0xe18, 0x24242424}, |
434 | {0xe1c, 0x24242424}, {0xe28, 0x00000000}, |
435 | {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f}, |
436 | {0xe38, 0x02140102}, {0xe3c, 0x681604c2}, |
437 | {0xe40, 0x01007c00}, {0xe44, 0x01004800}, |
438 | {0xe48, 0xfb000000}, {0xe4c, 0x000028d1}, |
439 | {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f}, |
440 | {0xe58, 0x02140102}, {0xe5c, 0x28160d05}, |
441 | {0xe60, 0x00000008}, {0xe68, 0x001b25a4}, |
442 | {0xe6c, 0x631b25a0}, {0xe70, 0x631b25a0}, |
443 | {0xe74, 0x081b25a0}, {0xe78, 0x081b25a0}, |
444 | {0xe7c, 0x081b25a0}, {0xe80, 0x081b25a0}, |
445 | {0xe84, 0x631b25a0}, {0xe88, 0x081b25a0}, |
446 | {0xe8c, 0x631b25a0}, {0xed0, 0x631b25a0}, |
447 | {0xed4, 0x631b25a0}, {0xed8, 0x631b25a0}, |
448 | {0xedc, 0x001b25a0}, {0xee0, 0x001b25a0}, |
449 | {0xeec, 0x6b1b25a0}, {0xee8, 0x31555448}, |
450 | {0xf14, 0x00000003}, {0xf4c, 0x00000000}, |
451 | {0xf00, 0x00000300}, |
452 | {0xffff, 0xffffffff}, |
453 | }; |
454 | |
455 | static const struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = { |
456 | {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, |
457 | {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, |
458 | {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, |
459 | {0xc78, 0x7a060001}, {0xc78, 0x79070001}, |
460 | {0xc78, 0x78080001}, {0xc78, 0x77090001}, |
461 | {0xc78, 0x760a0001}, {0xc78, 0x750b0001}, |
462 | {0xc78, 0x740c0001}, {0xc78, 0x730d0001}, |
463 | {0xc78, 0x720e0001}, {0xc78, 0x710f0001}, |
464 | {0xc78, 0x70100001}, {0xc78, 0x6f110001}, |
465 | {0xc78, 0x6e120001}, {0xc78, 0x6d130001}, |
466 | {0xc78, 0x6c140001}, {0xc78, 0x6b150001}, |
467 | {0xc78, 0x6a160001}, {0xc78, 0x69170001}, |
468 | {0xc78, 0x68180001}, {0xc78, 0x67190001}, |
469 | {0xc78, 0x661a0001}, {0xc78, 0x651b0001}, |
470 | {0xc78, 0x641c0001}, {0xc78, 0x631d0001}, |
471 | {0xc78, 0x621e0001}, {0xc78, 0x611f0001}, |
472 | {0xc78, 0x60200001}, {0xc78, 0x49210001}, |
473 | {0xc78, 0x48220001}, {0xc78, 0x47230001}, |
474 | {0xc78, 0x46240001}, {0xc78, 0x45250001}, |
475 | {0xc78, 0x44260001}, {0xc78, 0x43270001}, |
476 | {0xc78, 0x42280001}, {0xc78, 0x41290001}, |
477 | {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, |
478 | {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, |
479 | {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, |
480 | {0xc78, 0x21300001}, {0xc78, 0x20310001}, |
481 | {0xc78, 0x06320001}, {0xc78, 0x05330001}, |
482 | {0xc78, 0x04340001}, {0xc78, 0x03350001}, |
483 | {0xc78, 0x02360001}, {0xc78, 0x01370001}, |
484 | {0xc78, 0x00380001}, {0xc78, 0x00390001}, |
485 | {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, |
486 | {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, |
487 | {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, |
488 | {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, |
489 | {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, |
490 | {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, |
491 | {0xc78, 0x7a460001}, {0xc78, 0x79470001}, |
492 | {0xc78, 0x78480001}, {0xc78, 0x77490001}, |
493 | {0xc78, 0x764a0001}, {0xc78, 0x754b0001}, |
494 | {0xc78, 0x744c0001}, {0xc78, 0x734d0001}, |
495 | {0xc78, 0x724e0001}, {0xc78, 0x714f0001}, |
496 | {0xc78, 0x70500001}, {0xc78, 0x6f510001}, |
497 | {0xc78, 0x6e520001}, {0xc78, 0x6d530001}, |
498 | {0xc78, 0x6c540001}, {0xc78, 0x6b550001}, |
499 | {0xc78, 0x6a560001}, {0xc78, 0x69570001}, |
500 | {0xc78, 0x68580001}, {0xc78, 0x67590001}, |
501 | {0xc78, 0x665a0001}, {0xc78, 0x655b0001}, |
502 | {0xc78, 0x645c0001}, {0xc78, 0x635d0001}, |
503 | {0xc78, 0x625e0001}, {0xc78, 0x615f0001}, |
504 | {0xc78, 0x60600001}, {0xc78, 0x49610001}, |
505 | {0xc78, 0x48620001}, {0xc78, 0x47630001}, |
506 | {0xc78, 0x46640001}, {0xc78, 0x45650001}, |
507 | {0xc78, 0x44660001}, {0xc78, 0x43670001}, |
508 | {0xc78, 0x42680001}, {0xc78, 0x41690001}, |
509 | {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, |
510 | {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, |
511 | {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, |
512 | {0xc78, 0x21700001}, {0xc78, 0x20710001}, |
513 | {0xc78, 0x06720001}, {0xc78, 0x05730001}, |
514 | {0xc78, 0x04740001}, {0xc78, 0x03750001}, |
515 | {0xc78, 0x02760001}, {0xc78, 0x01770001}, |
516 | {0xc78, 0x00780001}, {0xc78, 0x00790001}, |
517 | {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, |
518 | {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, |
519 | {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, |
520 | {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, |
521 | {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, |
522 | {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, |
523 | {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, |
524 | {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, |
525 | {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, |
526 | {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, |
527 | {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, |
528 | {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, |
529 | {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, |
530 | {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, |
531 | {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, |
532 | {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, |
533 | {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, |
534 | {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, |
535 | {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, |
536 | {0xffff, 0xffffffff} |
537 | }; |
538 | |
539 | static const struct rtl8xxxu_reg32val rtl8xxx_agc_highpa_table[] = { |
540 | {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, |
541 | {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, |
542 | {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, |
543 | {0xc78, 0x7b060001}, {0xc78, 0x7b070001}, |
544 | {0xc78, 0x7b080001}, {0xc78, 0x7a090001}, |
545 | {0xc78, 0x790a0001}, {0xc78, 0x780b0001}, |
546 | {0xc78, 0x770c0001}, {0xc78, 0x760d0001}, |
547 | {0xc78, 0x750e0001}, {0xc78, 0x740f0001}, |
548 | {0xc78, 0x73100001}, {0xc78, 0x72110001}, |
549 | {0xc78, 0x71120001}, {0xc78, 0x70130001}, |
550 | {0xc78, 0x6f140001}, {0xc78, 0x6e150001}, |
551 | {0xc78, 0x6d160001}, {0xc78, 0x6c170001}, |
552 | {0xc78, 0x6b180001}, {0xc78, 0x6a190001}, |
553 | {0xc78, 0x691a0001}, {0xc78, 0x681b0001}, |
554 | {0xc78, 0x671c0001}, {0xc78, 0x661d0001}, |
555 | {0xc78, 0x651e0001}, {0xc78, 0x641f0001}, |
556 | {0xc78, 0x63200001}, {0xc78, 0x62210001}, |
557 | {0xc78, 0x61220001}, {0xc78, 0x60230001}, |
558 | {0xc78, 0x46240001}, {0xc78, 0x45250001}, |
559 | {0xc78, 0x44260001}, {0xc78, 0x43270001}, |
560 | {0xc78, 0x42280001}, {0xc78, 0x41290001}, |
561 | {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, |
562 | {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, |
563 | {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, |
564 | {0xc78, 0x21300001}, {0xc78, 0x20310001}, |
565 | {0xc78, 0x06320001}, {0xc78, 0x05330001}, |
566 | {0xc78, 0x04340001}, {0xc78, 0x03350001}, |
567 | {0xc78, 0x02360001}, {0xc78, 0x01370001}, |
568 | {0xc78, 0x00380001}, {0xc78, 0x00390001}, |
569 | {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, |
570 | {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, |
571 | {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, |
572 | {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, |
573 | {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, |
574 | {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, |
575 | {0xc78, 0x7b460001}, {0xc78, 0x7b470001}, |
576 | {0xc78, 0x7b480001}, {0xc78, 0x7a490001}, |
577 | {0xc78, 0x794a0001}, {0xc78, 0x784b0001}, |
578 | {0xc78, 0x774c0001}, {0xc78, 0x764d0001}, |
579 | {0xc78, 0x754e0001}, {0xc78, 0x744f0001}, |
580 | {0xc78, 0x73500001}, {0xc78, 0x72510001}, |
581 | {0xc78, 0x71520001}, {0xc78, 0x70530001}, |
582 | {0xc78, 0x6f540001}, {0xc78, 0x6e550001}, |
583 | {0xc78, 0x6d560001}, {0xc78, 0x6c570001}, |
584 | {0xc78, 0x6b580001}, {0xc78, 0x6a590001}, |
585 | {0xc78, 0x695a0001}, {0xc78, 0x685b0001}, |
586 | {0xc78, 0x675c0001}, {0xc78, 0x665d0001}, |
587 | {0xc78, 0x655e0001}, {0xc78, 0x645f0001}, |
588 | {0xc78, 0x63600001}, {0xc78, 0x62610001}, |
589 | {0xc78, 0x61620001}, {0xc78, 0x60630001}, |
590 | {0xc78, 0x46640001}, {0xc78, 0x45650001}, |
591 | {0xc78, 0x44660001}, {0xc78, 0x43670001}, |
592 | {0xc78, 0x42680001}, {0xc78, 0x41690001}, |
593 | {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, |
594 | {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, |
595 | {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, |
596 | {0xc78, 0x21700001}, {0xc78, 0x20710001}, |
597 | {0xc78, 0x06720001}, {0xc78, 0x05730001}, |
598 | {0xc78, 0x04740001}, {0xc78, 0x03750001}, |
599 | {0xc78, 0x02760001}, {0xc78, 0x01770001}, |
600 | {0xc78, 0x00780001}, {0xc78, 0x00790001}, |
601 | {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, |
602 | {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, |
603 | {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, |
604 | {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, |
605 | {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, |
606 | {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, |
607 | {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, |
608 | {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, |
609 | {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, |
610 | {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, |
611 | {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, |
612 | {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, |
613 | {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, |
614 | {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, |
615 | {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, |
616 | {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, |
617 | {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, |
618 | {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, |
619 | {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, |
620 | {0xffff, 0xffffffff} |
621 | }; |
622 | |
623 | static const struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { |
624 | { /* RF_A */ |
625 | .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1, |
626 | .hssiparm2 = REG_FPGA0_XA_HSSI_PARM2, |
627 | .lssiparm = REG_FPGA0_XA_LSSI_PARM, |
628 | .hspiread = REG_HSPI_XA_READBACK, |
629 | .lssiread = REG_FPGA0_XA_LSSI_READBACK, |
630 | .rf_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL, |
631 | }, |
632 | { /* RF_B */ |
633 | .hssiparm1 = REG_FPGA0_XB_HSSI_PARM1, |
634 | .hssiparm2 = REG_FPGA0_XB_HSSI_PARM2, |
635 | .lssiparm = REG_FPGA0_XB_LSSI_PARM, |
636 | .hspiread = REG_HSPI_XB_READBACK, |
637 | .lssiread = REG_FPGA0_XB_LSSI_READBACK, |
638 | .rf_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL, |
639 | }, |
640 | }; |
641 | |
642 | const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { |
643 | REG_OFDM0_XA_RX_IQ_IMBALANCE, |
644 | REG_OFDM0_XB_RX_IQ_IMBALANCE, |
645 | REG_OFDM0_ENERGY_CCA_THRES, |
646 | REG_OFDM0_AGC_RSSI_TABLE, |
647 | REG_OFDM0_XA_TX_IQ_IMBALANCE, |
648 | REG_OFDM0_XB_TX_IQ_IMBALANCE, |
649 | REG_OFDM0_XC_TX_AFE, |
650 | REG_OFDM0_XD_TX_AFE, |
651 | REG_OFDM0_RX_IQ_EXT_ANTA |
652 | }; |
653 | |
654 | u8 rtl8xxxu_read8(struct rtl8xxxu_priv *priv, u16 addr) |
655 | { |
656 | struct usb_device *udev = priv->udev; |
657 | int len; |
658 | u8 data; |
659 | |
660 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
661 | addr |= 0x8000; |
662 | |
663 | mutex_lock(&priv->usb_buf_mutex); |
664 | len = usb_control_msg(dev: udev, usb_rcvctrlpipe(udev, 0), |
665 | REALTEK_USB_CMD_REQ, REALTEK_USB_READ, |
666 | value: addr, index: 0, data: &priv->usb_buf.val8, size: sizeof(u8), |
667 | RTW_USB_CONTROL_MSG_TIMEOUT); |
668 | data = priv->usb_buf.val8; |
669 | mutex_unlock(lock: &priv->usb_buf_mutex); |
670 | |
671 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) |
672 | dev_info(&udev->dev, "%s(%04x) = 0x%02x, len %i\n" , |
673 | __func__, addr, data, len); |
674 | return data; |
675 | } |
676 | |
677 | u16 rtl8xxxu_read16(struct rtl8xxxu_priv *priv, u16 addr) |
678 | { |
679 | struct usb_device *udev = priv->udev; |
680 | int len; |
681 | u16 data; |
682 | |
683 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
684 | addr |= 0x8000; |
685 | |
686 | mutex_lock(&priv->usb_buf_mutex); |
687 | len = usb_control_msg(dev: udev, usb_rcvctrlpipe(udev, 0), |
688 | REALTEK_USB_CMD_REQ, REALTEK_USB_READ, |
689 | value: addr, index: 0, data: &priv->usb_buf.val16, size: sizeof(u16), |
690 | RTW_USB_CONTROL_MSG_TIMEOUT); |
691 | data = le16_to_cpu(priv->usb_buf.val16); |
692 | mutex_unlock(lock: &priv->usb_buf_mutex); |
693 | |
694 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) |
695 | dev_info(&udev->dev, "%s(%04x) = 0x%04x, len %i\n" , |
696 | __func__, addr, data, len); |
697 | return data; |
698 | } |
699 | |
700 | u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr) |
701 | { |
702 | struct usb_device *udev = priv->udev; |
703 | int len; |
704 | u32 data; |
705 | |
706 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
707 | addr |= 0x8000; |
708 | |
709 | mutex_lock(&priv->usb_buf_mutex); |
710 | len = usb_control_msg(dev: udev, usb_rcvctrlpipe(udev, 0), |
711 | REALTEK_USB_CMD_REQ, REALTEK_USB_READ, |
712 | value: addr, index: 0, data: &priv->usb_buf.val32, size: sizeof(u32), |
713 | RTW_USB_CONTROL_MSG_TIMEOUT); |
714 | data = le32_to_cpu(priv->usb_buf.val32); |
715 | mutex_unlock(lock: &priv->usb_buf_mutex); |
716 | |
717 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) |
718 | dev_info(&udev->dev, "%s(%04x) = 0x%08x, len %i\n" , |
719 | __func__, addr, data, len); |
720 | return data; |
721 | } |
722 | |
723 | int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val) |
724 | { |
725 | struct usb_device *udev = priv->udev; |
726 | int ret; |
727 | |
728 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
729 | addr |= 0x8000; |
730 | |
731 | mutex_lock(&priv->usb_buf_mutex); |
732 | priv->usb_buf.val8 = val; |
733 | ret = usb_control_msg(dev: udev, usb_sndctrlpipe(udev, 0), |
734 | REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, |
735 | value: addr, index: 0, data: &priv->usb_buf.val8, size: sizeof(u8), |
736 | RTW_USB_CONTROL_MSG_TIMEOUT); |
737 | |
738 | mutex_unlock(lock: &priv->usb_buf_mutex); |
739 | |
740 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) |
741 | dev_info(&udev->dev, "%s(%04x) = 0x%02x\n" , |
742 | __func__, addr, val); |
743 | return ret; |
744 | } |
745 | |
746 | int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val) |
747 | { |
748 | struct usb_device *udev = priv->udev; |
749 | int ret; |
750 | |
751 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
752 | addr |= 0x8000; |
753 | |
754 | mutex_lock(&priv->usb_buf_mutex); |
755 | priv->usb_buf.val16 = cpu_to_le16(val); |
756 | ret = usb_control_msg(dev: udev, usb_sndctrlpipe(udev, 0), |
757 | REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, |
758 | value: addr, index: 0, data: &priv->usb_buf.val16, size: sizeof(u16), |
759 | RTW_USB_CONTROL_MSG_TIMEOUT); |
760 | mutex_unlock(lock: &priv->usb_buf_mutex); |
761 | |
762 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) |
763 | dev_info(&udev->dev, "%s(%04x) = 0x%04x\n" , |
764 | __func__, addr, val); |
765 | return ret; |
766 | } |
767 | |
768 | int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val) |
769 | { |
770 | struct usb_device *udev = priv->udev; |
771 | int ret; |
772 | |
773 | if (priv->rtl_chip == RTL8710B && addr <= 0xff) |
774 | addr |= 0x8000; |
775 | |
776 | mutex_lock(&priv->usb_buf_mutex); |
777 | priv->usb_buf.val32 = cpu_to_le32(val); |
778 | ret = usb_control_msg(dev: udev, usb_sndctrlpipe(udev, 0), |
779 | REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, |
780 | value: addr, index: 0, data: &priv->usb_buf.val32, size: sizeof(u32), |
781 | RTW_USB_CONTROL_MSG_TIMEOUT); |
782 | mutex_unlock(lock: &priv->usb_buf_mutex); |
783 | |
784 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) |
785 | dev_info(&udev->dev, "%s(%04x) = 0x%08x\n" , |
786 | __func__, addr, val); |
787 | return ret; |
788 | } |
789 | |
790 | int rtl8xxxu_write8_set(struct rtl8xxxu_priv *priv, u16 addr, u8 bits) |
791 | { |
792 | u8 val8; |
793 | |
794 | val8 = rtl8xxxu_read8(priv, addr); |
795 | val8 |= bits; |
796 | return rtl8xxxu_write8(priv, addr, val: val8); |
797 | } |
798 | |
799 | int rtl8xxxu_write8_clear(struct rtl8xxxu_priv *priv, u16 addr, u8 bits) |
800 | { |
801 | u8 val8; |
802 | |
803 | val8 = rtl8xxxu_read8(priv, addr); |
804 | val8 &= ~bits; |
805 | return rtl8xxxu_write8(priv, addr, val: val8); |
806 | } |
807 | |
808 | int rtl8xxxu_write16_set(struct rtl8xxxu_priv *priv, u16 addr, u16 bits) |
809 | { |
810 | u16 val16; |
811 | |
812 | val16 = rtl8xxxu_read16(priv, addr); |
813 | val16 |= bits; |
814 | return rtl8xxxu_write16(priv, addr, val: val16); |
815 | } |
816 | |
817 | int rtl8xxxu_write16_clear(struct rtl8xxxu_priv *priv, u16 addr, u16 bits) |
818 | { |
819 | u16 val16; |
820 | |
821 | val16 = rtl8xxxu_read16(priv, addr); |
822 | val16 &= ~bits; |
823 | return rtl8xxxu_write16(priv, addr, val: val16); |
824 | } |
825 | |
826 | int rtl8xxxu_write32_set(struct rtl8xxxu_priv *priv, u16 addr, u32 bits) |
827 | { |
828 | u32 val32; |
829 | |
830 | val32 = rtl8xxxu_read32(priv, addr); |
831 | val32 |= bits; |
832 | return rtl8xxxu_write32(priv, addr, val: val32); |
833 | } |
834 | |
835 | int rtl8xxxu_write32_clear(struct rtl8xxxu_priv *priv, u16 addr, u32 bits) |
836 | { |
837 | u32 val32; |
838 | |
839 | val32 = rtl8xxxu_read32(priv, addr); |
840 | val32 &= ~bits; |
841 | return rtl8xxxu_write32(priv, addr, val: val32); |
842 | } |
843 | |
844 | int rtl8xxxu_write32_mask(struct rtl8xxxu_priv *priv, u16 addr, |
845 | u32 mask, u32 val) |
846 | { |
847 | u32 orig, new, shift; |
848 | |
849 | shift = __ffs(mask); |
850 | |
851 | orig = rtl8xxxu_read32(priv, addr); |
852 | new = (orig & ~mask) | ((val << shift) & mask); |
853 | return rtl8xxxu_write32(priv, addr, val: new); |
854 | } |
855 | |
856 | int rtl8xxxu_write_rfreg_mask(struct rtl8xxxu_priv *priv, |
857 | enum rtl8xxxu_rfpath path, u8 reg, |
858 | u32 mask, u32 val) |
859 | { |
860 | u32 orig, new, shift; |
861 | |
862 | shift = __ffs(mask); |
863 | |
864 | orig = rtl8xxxu_read_rfreg(priv, path, reg); |
865 | new = (orig & ~mask) | ((val << shift) & mask); |
866 | return rtl8xxxu_write_rfreg(priv, path, reg, data: new); |
867 | } |
868 | |
869 | static int |
870 | rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len) |
871 | { |
872 | struct usb_device *udev = priv->udev; |
873 | int blocksize = priv->fops->writeN_block_size; |
874 | int ret, i, count, remainder; |
875 | |
876 | count = len / blocksize; |
877 | remainder = len % blocksize; |
878 | |
879 | for (i = 0; i < count; i++) { |
880 | ret = usb_control_msg(dev: udev, usb_sndctrlpipe(udev, 0), |
881 | REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, |
882 | value: addr, index: 0, data: buf, size: blocksize, |
883 | RTW_USB_CONTROL_MSG_TIMEOUT); |
884 | if (ret != blocksize) |
885 | goto write_error; |
886 | |
887 | addr += blocksize; |
888 | buf += blocksize; |
889 | } |
890 | |
891 | if (remainder) { |
892 | ret = usb_control_msg(dev: udev, usb_sndctrlpipe(udev, 0), |
893 | REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, |
894 | value: addr, index: 0, data: buf, size: remainder, |
895 | RTW_USB_CONTROL_MSG_TIMEOUT); |
896 | if (ret != remainder) |
897 | goto write_error; |
898 | } |
899 | |
900 | return len; |
901 | |
902 | write_error: |
903 | dev_info(&udev->dev, |
904 | "%s: Failed to write block at addr: %04x size: %04x\n" , |
905 | __func__, addr, blocksize); |
906 | return -EAGAIN; |
907 | } |
908 | |
909 | u32 rtl8xxxu_read_rfreg(struct rtl8xxxu_priv *priv, |
910 | enum rtl8xxxu_rfpath path, u8 reg) |
911 | { |
912 | u32 hssia, val32, retval; |
913 | |
914 | hssia = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); |
915 | if (path != RF_A) |
916 | val32 = rtl8xxxu_read32(priv, addr: rtl8xxxu_rfregs[path].hssiparm2); |
917 | else |
918 | val32 = hssia; |
919 | |
920 | val32 &= ~FPGA0_HSSI_PARM2_ADDR_MASK; |
921 | val32 |= (reg << FPGA0_HSSI_PARM2_ADDR_SHIFT); |
922 | val32 |= FPGA0_HSSI_PARM2_EDGE_READ; |
923 | hssia &= ~FPGA0_HSSI_PARM2_EDGE_READ; |
924 | rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, val: hssia); |
925 | |
926 | udelay(10); |
927 | |
928 | rtl8xxxu_write32(priv, addr: rtl8xxxu_rfregs[path].hssiparm2, val: val32); |
929 | udelay(100); |
930 | |
931 | hssia |= FPGA0_HSSI_PARM2_EDGE_READ; |
932 | rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, val: hssia); |
933 | udelay(10); |
934 | |
935 | val32 = rtl8xxxu_read32(priv, addr: rtl8xxxu_rfregs[path].hssiparm1); |
936 | if (val32 & FPGA0_HSSI_PARM1_PI) |
937 | retval = rtl8xxxu_read32(priv, addr: rtl8xxxu_rfregs[path].hspiread); |
938 | else |
939 | retval = rtl8xxxu_read32(priv, addr: rtl8xxxu_rfregs[path].lssiread); |
940 | |
941 | retval &= 0xfffff; |
942 | |
943 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_READ) |
944 | dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n" , |
945 | __func__, reg, retval); |
946 | return retval; |
947 | } |
948 | |
949 | /* |
950 | * The RTL8723BU driver indicates that registers 0xb2 and 0xb6 can |
951 | * have write issues in high temperature conditions. We may have to |
952 | * retry writing them. |
953 | */ |
954 | int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, |
955 | enum rtl8xxxu_rfpath path, u8 reg, u32 data) |
956 | { |
957 | int ret, retval; |
958 | u32 dataaddr, val32; |
959 | |
960 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE) |
961 | dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n" , |
962 | __func__, reg, data); |
963 | |
964 | data &= FPGA0_LSSI_PARM_DATA_MASK; |
965 | dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data; |
966 | |
967 | if (priv->rtl_chip == RTL8192E) { |
968 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); |
969 | val32 &= ~0x20000; |
970 | rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val: val32); |
971 | } |
972 | |
973 | /* Use XB for path B */ |
974 | ret = rtl8xxxu_write32(priv, addr: rtl8xxxu_rfregs[path].lssiparm, val: dataaddr); |
975 | if (ret != sizeof(dataaddr)) |
976 | retval = -EIO; |
977 | else |
978 | retval = 0; |
979 | |
980 | udelay(1); |
981 | |
982 | if (priv->rtl_chip == RTL8192E) { |
983 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); |
984 | val32 |= 0x20000; |
985 | rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val: val32); |
986 | } |
987 | |
988 | return retval; |
989 | } |
990 | |
991 | static int |
992 | rtl8xxxu_gen1_h2c_cmd(struct rtl8xxxu_priv *priv, struct h2c_cmd *h2c, int len) |
993 | { |
994 | struct device *dev = &priv->udev->dev; |
995 | int mbox_nr, retry, retval = 0; |
996 | int mbox_reg, mbox_ext_reg; |
997 | u8 val8; |
998 | |
999 | mutex_lock(&priv->h2c_mutex); |
1000 | |
1001 | mbox_nr = priv->next_mbox; |
1002 | mbox_reg = REG_HMBOX_0 + (mbox_nr * 4); |
1003 | mbox_ext_reg = REG_HMBOX_EXT_0 + (mbox_nr * 2); |
1004 | |
1005 | /* |
1006 | * MBOX ready? |
1007 | */ |
1008 | retry = 100; |
1009 | do { |
1010 | val8 = rtl8xxxu_read8(priv, REG_HMTFR); |
1011 | if (!(val8 & BIT(mbox_nr))) |
1012 | break; |
1013 | } while (retry--); |
1014 | |
1015 | if (!retry) { |
1016 | dev_info(dev, "%s: Mailbox busy\n" , __func__); |
1017 | retval = -EBUSY; |
1018 | goto error; |
1019 | } |
1020 | |
1021 | /* |
1022 | * Need to swap as it's being swapped again by rtl8xxxu_write16/32() |
1023 | */ |
1024 | if (len > sizeof(u32)) { |
1025 | rtl8xxxu_write16(priv, addr: mbox_ext_reg, le16_to_cpu(h2c->raw.ext)); |
1026 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) |
1027 | dev_info(dev, "H2C_EXT %04x\n" , |
1028 | le16_to_cpu(h2c->raw.ext)); |
1029 | } |
1030 | rtl8xxxu_write32(priv, addr: mbox_reg, le32_to_cpu(h2c->raw.data)); |
1031 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) |
1032 | dev_info(dev, "H2C %08x\n" , le32_to_cpu(h2c->raw.data)); |
1033 | |
1034 | priv->next_mbox = (mbox_nr + 1) % H2C_MAX_MBOX; |
1035 | |
1036 | error: |
1037 | mutex_unlock(lock: &priv->h2c_mutex); |
1038 | return retval; |
1039 | } |
1040 | |
1041 | int |
1042 | rtl8xxxu_gen2_h2c_cmd(struct rtl8xxxu_priv *priv, struct h2c_cmd *h2c, int len) |
1043 | { |
1044 | struct device *dev = &priv->udev->dev; |
1045 | int mbox_nr, retry, retval = 0; |
1046 | int mbox_reg, mbox_ext_reg; |
1047 | u8 val8; |
1048 | |
1049 | mutex_lock(&priv->h2c_mutex); |
1050 | |
1051 | mbox_nr = priv->next_mbox; |
1052 | mbox_reg = REG_HMBOX_0 + (mbox_nr * 4); |
1053 | mbox_ext_reg = REG_HMBOX_EXT0_8723B + (mbox_nr * 4); |
1054 | |
1055 | /* |
1056 | * MBOX ready? |
1057 | */ |
1058 | retry = 100; |
1059 | do { |
1060 | val8 = rtl8xxxu_read8(priv, REG_HMTFR); |
1061 | if (!(val8 & BIT(mbox_nr))) |
1062 | break; |
1063 | } while (retry--); |
1064 | |
1065 | if (!retry) { |
1066 | dev_info(dev, "%s: Mailbox busy\n" , __func__); |
1067 | retval = -EBUSY; |
1068 | goto error; |
1069 | } |
1070 | |
1071 | /* |
1072 | * Need to swap as it's being swapped again by rtl8xxxu_write16/32() |
1073 | */ |
1074 | if (len > sizeof(u32)) { |
1075 | rtl8xxxu_write32(priv, addr: mbox_ext_reg, |
1076 | le32_to_cpu(h2c->raw_wide.ext)); |
1077 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) |
1078 | dev_info(dev, "H2C_EXT %08x\n" , |
1079 | le32_to_cpu(h2c->raw_wide.ext)); |
1080 | } |
1081 | rtl8xxxu_write32(priv, addr: mbox_reg, le32_to_cpu(h2c->raw.data)); |
1082 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) |
1083 | dev_info(dev, "H2C %08x\n" , le32_to_cpu(h2c->raw.data)); |
1084 | |
1085 | priv->next_mbox = (mbox_nr + 1) % H2C_MAX_MBOX; |
1086 | |
1087 | error: |
1088 | mutex_unlock(lock: &priv->h2c_mutex); |
1089 | return retval; |
1090 | } |
1091 | |
1092 | void rtl8xxxu_gen1_enable_rf(struct rtl8xxxu_priv *priv) |
1093 | { |
1094 | u8 val8; |
1095 | u32 val32; |
1096 | |
1097 | val8 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); |
1098 | val8 |= BIT(0) | BIT(3); |
1099 | rtl8xxxu_write8(priv, REG_SPS0_CTRL, val: val8); |
1100 | |
1101 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); |
1102 | val32 &= ~(BIT(4) | BIT(5)); |
1103 | val32 |= BIT(3); |
1104 | if (priv->rf_paths == 2) { |
1105 | val32 &= ~(BIT(20) | BIT(21)); |
1106 | val32 |= BIT(19); |
1107 | } |
1108 | rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val: val32); |
1109 | |
1110 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); |
1111 | val32 &= ~OFDM_RF_PATH_TX_MASK; |
1112 | if (priv->tx_paths == 2) |
1113 | val32 |= OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; |
1114 | else if (priv->rtl_chip == RTL8192C || priv->rtl_chip == RTL8191C) |
1115 | val32 |= OFDM_RF_PATH_TX_B; |
1116 | else |
1117 | val32 |= OFDM_RF_PATH_TX_A; |
1118 | rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val: val32); |
1119 | |
1120 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1121 | val32 &= ~FPGA_RF_MODE_JAPAN; |
1122 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1123 | |
1124 | if (priv->rf_paths == 2) |
1125 | rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val: 0x63db25a0); |
1126 | else |
1127 | rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val: 0x631b25a0); |
1128 | |
1129 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_AC, data: 0x32d95); |
1130 | if (priv->rf_paths == 2) |
1131 | rtl8xxxu_write_rfreg(priv, path: RF_B, RF6052_REG_AC, data: 0x32d95); |
1132 | |
1133 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0x00); |
1134 | } |
1135 | |
1136 | void rtl8xxxu_gen1_disable_rf(struct rtl8xxxu_priv *priv) |
1137 | { |
1138 | u8 sps0; |
1139 | u32 val32; |
1140 | |
1141 | sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); |
1142 | |
1143 | /* RF RX code for preamble power saving */ |
1144 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); |
1145 | val32 &= ~(BIT(3) | BIT(4) | BIT(5)); |
1146 | if (priv->rf_paths == 2) |
1147 | val32 &= ~(BIT(19) | BIT(20) | BIT(21)); |
1148 | rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val: val32); |
1149 | |
1150 | /* Disable TX for four paths */ |
1151 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); |
1152 | val32 &= ~OFDM_RF_PATH_TX_MASK; |
1153 | rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val: val32); |
1154 | |
1155 | /* Enable power saving */ |
1156 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1157 | val32 |= FPGA_RF_MODE_JAPAN; |
1158 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1159 | |
1160 | /* AFE control register to power down bits [30:22] */ |
1161 | if (priv->rf_paths == 2) |
1162 | rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val: 0x00db25a0); |
1163 | else |
1164 | rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val: 0x001b25a0); |
1165 | |
1166 | /* Power down RF module */ |
1167 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_AC, data: 0); |
1168 | if (priv->rf_paths == 2) |
1169 | rtl8xxxu_write_rfreg(priv, path: RF_B, RF6052_REG_AC, data: 0); |
1170 | |
1171 | sps0 &= ~(BIT(0) | BIT(3)); |
1172 | rtl8xxxu_write8(priv, REG_SPS0_CTRL, val: sps0); |
1173 | } |
1174 | |
1175 | static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv) |
1176 | { |
1177 | u8 val8; |
1178 | |
1179 | val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2); |
1180 | val8 &= ~BIT(6); |
1181 | rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val: val8); |
1182 | |
1183 | rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, val: 0x64); |
1184 | val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2); |
1185 | val8 &= ~BIT(0); |
1186 | rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val: val8); |
1187 | } |
1188 | |
1189 | static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv) |
1190 | { |
1191 | u8 val8; |
1192 | |
1193 | val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2); |
1194 | val8 |= EN_BCNQ_DL >> 16; |
1195 | rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val: val8); |
1196 | |
1197 | rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, val: 0x80); |
1198 | val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2); |
1199 | val8 &= 0xF0; |
1200 | rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val: val8); |
1201 | } |
1202 | |
1203 | |
1204 | /* |
1205 | * The rtl8723a has 3 channel groups for it's efuse settings. It only |
1206 | * supports the 2.4GHz band, so channels 1 - 14: |
1207 | * group 0: channels 1 - 3 |
1208 | * group 1: channels 4 - 9 |
1209 | * group 2: channels 10 - 14 |
1210 | * |
1211 | * Note: We index from 0 in the code |
1212 | */ |
1213 | static int rtl8xxxu_gen1_channel_to_group(int channel) |
1214 | { |
1215 | int group; |
1216 | |
1217 | if (channel < 4) |
1218 | group = 0; |
1219 | else if (channel < 10) |
1220 | group = 1; |
1221 | else |
1222 | group = 2; |
1223 | |
1224 | return group; |
1225 | } |
1226 | |
1227 | /* |
1228 | * Valid for rtl8723bu and rtl8192eu |
1229 | */ |
1230 | int rtl8xxxu_gen2_channel_to_group(int channel) |
1231 | { |
1232 | int group; |
1233 | |
1234 | if (channel < 3) |
1235 | group = 0; |
1236 | else if (channel < 6) |
1237 | group = 1; |
1238 | else if (channel < 9) |
1239 | group = 2; |
1240 | else if (channel < 12) |
1241 | group = 3; |
1242 | else |
1243 | group = 4; |
1244 | |
1245 | return group; |
1246 | } |
1247 | |
1248 | void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) |
1249 | { |
1250 | struct rtl8xxxu_priv *priv = hw->priv; |
1251 | u32 val32, rsr; |
1252 | u8 val8, opmode; |
1253 | bool ht = true; |
1254 | int sec_ch_above, channel; |
1255 | int i; |
1256 | |
1257 | opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE); |
1258 | rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); |
1259 | channel = hw->conf.chandef.chan->hw_value; |
1260 | |
1261 | switch (hw->conf.chandef.width) { |
1262 | case NL80211_CHAN_WIDTH_20_NOHT: |
1263 | ht = false; |
1264 | fallthrough; |
1265 | case NL80211_CHAN_WIDTH_20: |
1266 | opmode |= BW_OPMODE_20MHZ; |
1267 | rtl8xxxu_write8(priv, REG_BW_OPMODE, val: opmode); |
1268 | |
1269 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1270 | val32 &= ~FPGA_RF_MODE; |
1271 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1272 | |
1273 | val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); |
1274 | val32 &= ~FPGA_RF_MODE; |
1275 | rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val: val32); |
1276 | |
1277 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); |
1278 | val32 |= FPGA0_ANALOG2_20MHZ; |
1279 | rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val: val32); |
1280 | break; |
1281 | case NL80211_CHAN_WIDTH_40: |
1282 | if (hw->conf.chandef.center_freq1 > |
1283 | hw->conf.chandef.chan->center_freq) { |
1284 | sec_ch_above = 1; |
1285 | channel += 2; |
1286 | } else { |
1287 | sec_ch_above = 0; |
1288 | channel -= 2; |
1289 | } |
1290 | |
1291 | opmode &= ~BW_OPMODE_20MHZ; |
1292 | rtl8xxxu_write8(priv, REG_BW_OPMODE, val: opmode); |
1293 | rsr &= ~RSR_RSC_BANDWIDTH_40M; |
1294 | if (sec_ch_above) |
1295 | rsr |= RSR_RSC_UPPER_SUB_CHANNEL; |
1296 | else |
1297 | rsr |= RSR_RSC_LOWER_SUB_CHANNEL; |
1298 | rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val: rsr); |
1299 | |
1300 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1301 | val32 |= FPGA_RF_MODE; |
1302 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1303 | |
1304 | val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); |
1305 | val32 |= FPGA_RF_MODE; |
1306 | rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val: val32); |
1307 | |
1308 | /* |
1309 | * Set Control channel to upper or lower. These settings |
1310 | * are required only for 40MHz |
1311 | */ |
1312 | val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM); |
1313 | val32 &= ~CCK0_SIDEBAND; |
1314 | if (!sec_ch_above) |
1315 | val32 |= CCK0_SIDEBAND; |
1316 | rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val: val32); |
1317 | |
1318 | val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); |
1319 | val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */ |
1320 | if (sec_ch_above) |
1321 | val32 |= OFDM_LSTF_PRIME_CH_LOW; |
1322 | else |
1323 | val32 |= OFDM_LSTF_PRIME_CH_HIGH; |
1324 | rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val: val32); |
1325 | |
1326 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); |
1327 | val32 &= ~FPGA0_ANALOG2_20MHZ; |
1328 | rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val: val32); |
1329 | |
1330 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); |
1331 | val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL); |
1332 | if (sec_ch_above) |
1333 | val32 |= FPGA0_PS_UPPER_CHANNEL; |
1334 | else |
1335 | val32 |= FPGA0_PS_LOWER_CHANNEL; |
1336 | rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val: val32); |
1337 | break; |
1338 | |
1339 | default: |
1340 | break; |
1341 | } |
1342 | |
1343 | for (i = RF_A; i < priv->rf_paths; i++) { |
1344 | val32 = rtl8xxxu_read_rfreg(priv, path: i, RF6052_REG_MODE_AG); |
1345 | val32 &= ~MODE_AG_CHANNEL_MASK; |
1346 | val32 |= channel; |
1347 | rtl8xxxu_write_rfreg(priv, path: i, RF6052_REG_MODE_AG, data: val32); |
1348 | } |
1349 | |
1350 | if (ht) |
1351 | val8 = 0x0e; |
1352 | else |
1353 | val8 = 0x0a; |
1354 | |
1355 | rtl8xxxu_write8(priv, REG_SIFS_CCK + 1, val: val8); |
1356 | rtl8xxxu_write8(priv, REG_SIFS_OFDM + 1, val: val8); |
1357 | |
1358 | rtl8xxxu_write16(priv, REG_R2T_SIFS, val: 0x0808); |
1359 | rtl8xxxu_write16(priv, REG_T2T_SIFS, val: 0x0a0a); |
1360 | |
1361 | for (i = RF_A; i < priv->rf_paths; i++) { |
1362 | val32 = rtl8xxxu_read_rfreg(priv, path: i, RF6052_REG_MODE_AG); |
1363 | if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) |
1364 | val32 &= ~MODE_AG_CHANNEL_20MHZ; |
1365 | else |
1366 | val32 |= MODE_AG_CHANNEL_20MHZ; |
1367 | rtl8xxxu_write_rfreg(priv, path: i, RF6052_REG_MODE_AG, data: val32); |
1368 | } |
1369 | } |
1370 | |
1371 | void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) |
1372 | { |
1373 | struct rtl8xxxu_priv *priv = hw->priv; |
1374 | u32 val32; |
1375 | u8 val8, subchannel; |
1376 | u16 rf_mode_bw; |
1377 | bool ht = true; |
1378 | int sec_ch_above, channel; |
1379 | int i; |
1380 | |
1381 | rf_mode_bw = rtl8xxxu_read16(priv, REG_WMAC_TRXPTCL_CTL); |
1382 | rf_mode_bw &= ~WMAC_TRXPTCL_CTL_BW_MASK; |
1383 | channel = hw->conf.chandef.chan->hw_value; |
1384 | |
1385 | /* Hack */ |
1386 | subchannel = 0; |
1387 | |
1388 | switch (hw->conf.chandef.width) { |
1389 | case NL80211_CHAN_WIDTH_20_NOHT: |
1390 | ht = false; |
1391 | fallthrough; |
1392 | case NL80211_CHAN_WIDTH_20: |
1393 | rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_20; |
1394 | subchannel = 0; |
1395 | |
1396 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1397 | val32 &= ~FPGA_RF_MODE; |
1398 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1399 | |
1400 | val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); |
1401 | val32 &= ~FPGA_RF_MODE; |
1402 | rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val: val32); |
1403 | |
1404 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT); |
1405 | val32 &= ~(BIT(30) | BIT(31)); |
1406 | rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val: val32); |
1407 | |
1408 | break; |
1409 | case NL80211_CHAN_WIDTH_40: |
1410 | rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_40; |
1411 | |
1412 | if (hw->conf.chandef.center_freq1 > |
1413 | hw->conf.chandef.chan->center_freq) { |
1414 | sec_ch_above = 1; |
1415 | channel += 2; |
1416 | } else { |
1417 | sec_ch_above = 0; |
1418 | channel -= 2; |
1419 | } |
1420 | |
1421 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
1422 | val32 |= FPGA_RF_MODE; |
1423 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
1424 | |
1425 | val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); |
1426 | val32 |= FPGA_RF_MODE; |
1427 | rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val: val32); |
1428 | |
1429 | /* |
1430 | * Set Control channel to upper or lower. These settings |
1431 | * are required only for 40MHz |
1432 | */ |
1433 | val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM); |
1434 | val32 &= ~CCK0_SIDEBAND; |
1435 | if (!sec_ch_above) |
1436 | val32 |= CCK0_SIDEBAND; |
1437 | rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val: val32); |
1438 | |
1439 | val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); |
1440 | val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */ |
1441 | if (sec_ch_above) |
1442 | val32 |= OFDM_LSTF_PRIME_CH_LOW; |
1443 | else |
1444 | val32 |= OFDM_LSTF_PRIME_CH_HIGH; |
1445 | rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val: val32); |
1446 | |
1447 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); |
1448 | val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL); |
1449 | if (sec_ch_above) |
1450 | val32 |= FPGA0_PS_UPPER_CHANNEL; |
1451 | else |
1452 | val32 |= FPGA0_PS_LOWER_CHANNEL; |
1453 | rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val: val32); |
1454 | break; |
1455 | case NL80211_CHAN_WIDTH_80: |
1456 | rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_80; |
1457 | break; |
1458 | default: |
1459 | break; |
1460 | } |
1461 | |
1462 | for (i = RF_A; i < priv->rf_paths; i++) { |
1463 | val32 = rtl8xxxu_read_rfreg(priv, path: i, RF6052_REG_MODE_AG); |
1464 | val32 &= ~MODE_AG_CHANNEL_MASK; |
1465 | val32 |= channel; |
1466 | rtl8xxxu_write_rfreg(priv, path: i, RF6052_REG_MODE_AG, data: val32); |
1467 | } |
1468 | |
1469 | rtl8xxxu_write16(priv, REG_WMAC_TRXPTCL_CTL, val: rf_mode_bw); |
1470 | rtl8xxxu_write8(priv, REG_DATA_SUBCHANNEL, val: subchannel); |
1471 | |
1472 | if (ht) |
1473 | val8 = 0x0e; |
1474 | else |
1475 | val8 = 0x0a; |
1476 | |
1477 | rtl8xxxu_write8(priv, REG_SIFS_CCK + 1, val: val8); |
1478 | rtl8xxxu_write8(priv, REG_SIFS_OFDM + 1, val: val8); |
1479 | |
1480 | rtl8xxxu_write16(priv, REG_R2T_SIFS, val: 0x0808); |
1481 | rtl8xxxu_write16(priv, REG_T2T_SIFS, val: 0x0a0a); |
1482 | |
1483 | for (i = RF_A; i < priv->rf_paths; i++) { |
1484 | val32 = rtl8xxxu_read_rfreg(priv, path: i, RF6052_REG_MODE_AG); |
1485 | val32 &= ~MODE_AG_BW_MASK; |
1486 | switch(hw->conf.chandef.width) { |
1487 | case NL80211_CHAN_WIDTH_80: |
1488 | val32 |= MODE_AG_BW_80MHZ_8723B; |
1489 | break; |
1490 | case NL80211_CHAN_WIDTH_40: |
1491 | val32 |= MODE_AG_BW_40MHZ_8723B; |
1492 | break; |
1493 | default: |
1494 | val32 |= MODE_AG_BW_20MHZ_8723B; |
1495 | break; |
1496 | } |
1497 | rtl8xxxu_write_rfreg(priv, path: i, RF6052_REG_MODE_AG, data: val32); |
1498 | } |
1499 | } |
1500 | |
1501 | void |
1502 | rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) |
1503 | { |
1504 | struct rtl8xxxu_power_base *power_base = priv->power_base; |
1505 | u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; |
1506 | u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS]; |
1507 | u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b; |
1508 | u8 val8; |
1509 | int group, i; |
1510 | |
1511 | group = rtl8xxxu_gen1_channel_to_group(channel); |
1512 | |
1513 | cck[0] = priv->cck_tx_power_index_A[group] - 1; |
1514 | cck[1] = priv->cck_tx_power_index_B[group] - 1; |
1515 | |
1516 | if (priv->hi_pa) { |
1517 | if (cck[0] > 0x20) |
1518 | cck[0] = 0x20; |
1519 | if (cck[1] > 0x20) |
1520 | cck[1] = 0x20; |
1521 | } |
1522 | |
1523 | ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; |
1524 | ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; |
1525 | if (ofdm[0]) |
1526 | ofdm[0] -= 1; |
1527 | if (ofdm[1]) |
1528 | ofdm[1] -= 1; |
1529 | |
1530 | ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a; |
1531 | ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b; |
1532 | |
1533 | mcsbase[0] = ofdm[0]; |
1534 | mcsbase[1] = ofdm[1]; |
1535 | if (!ht40) { |
1536 | mcsbase[0] += priv->ht20_tx_power_index_diff[group].a; |
1537 | mcsbase[1] += priv->ht20_tx_power_index_diff[group].b; |
1538 | } |
1539 | |
1540 | if (priv->tx_paths > 1) { |
1541 | if (ofdm[0] > priv->ht40_2s_tx_power_index_diff[group].a) |
1542 | ofdm[0] -= priv->ht40_2s_tx_power_index_diff[group].a; |
1543 | if (ofdm[1] > priv->ht40_2s_tx_power_index_diff[group].b) |
1544 | ofdm[1] -= priv->ht40_2s_tx_power_index_diff[group].b; |
1545 | } |
1546 | |
1547 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) |
1548 | dev_info(&priv->udev->dev, |
1549 | "%s: Setting TX power CCK A: %02x, " |
1550 | "CCK B: %02x, OFDM A: %02x, OFDM B: %02x\n" , |
1551 | __func__, cck[0], cck[1], ofdm[0], ofdm[1]); |
1552 | |
1553 | for (i = 0; i < RTL8723A_MAX_RF_PATHS; i++) { |
1554 | if (cck[i] > RF6052_MAX_TX_PWR) |
1555 | cck[i] = RF6052_MAX_TX_PWR; |
1556 | if (ofdm[i] > RF6052_MAX_TX_PWR) |
1557 | ofdm[i] = RF6052_MAX_TX_PWR; |
1558 | } |
1559 | |
1560 | val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); |
1561 | val32 &= 0xffff00ff; |
1562 | val32 |= (cck[0] << 8); |
1563 | rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val: val32); |
1564 | |
1565 | val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); |
1566 | val32 &= 0xff; |
1567 | val32 |= ((cck[0] << 8) | (cck[0] << 16) | (cck[0] << 24)); |
1568 | rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val: val32); |
1569 | |
1570 | val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); |
1571 | val32 &= 0xffffff00; |
1572 | val32 |= cck[1]; |
1573 | rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val: val32); |
1574 | |
1575 | val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32); |
1576 | val32 &= 0xff; |
1577 | val32 |= ((cck[1] << 8) | (cck[1] << 16) | (cck[1] << 24)); |
1578 | rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val: val32); |
1579 | |
1580 | ofdm_a = ofdmbase[0] | ofdmbase[0] << 8 | |
1581 | ofdmbase[0] << 16 | ofdmbase[0] << 24; |
1582 | ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 | |
1583 | ofdmbase[1] << 16 | ofdmbase[1] << 24; |
1584 | |
1585 | rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, |
1586 | val: ofdm_a + power_base->reg_0e00); |
1587 | rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, |
1588 | val: ofdm_b + power_base->reg_0830); |
1589 | |
1590 | rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, |
1591 | val: ofdm_a + power_base->reg_0e04); |
1592 | rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, |
1593 | val: ofdm_b + power_base->reg_0834); |
1594 | |
1595 | mcs_a = mcsbase[0] | mcsbase[0] << 8 | |
1596 | mcsbase[0] << 16 | mcsbase[0] << 24; |
1597 | mcs_b = mcsbase[1] | mcsbase[1] << 8 | |
1598 | mcsbase[1] << 16 | mcsbase[1] << 24; |
1599 | |
1600 | rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, |
1601 | val: mcs_a + power_base->reg_0e10); |
1602 | rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, |
1603 | val: mcs_b + power_base->reg_083c); |
1604 | |
1605 | rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, |
1606 | val: mcs_a + power_base->reg_0e14); |
1607 | rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, |
1608 | val: mcs_b + power_base->reg_0848); |
1609 | |
1610 | rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, |
1611 | val: mcs_a + power_base->reg_0e18); |
1612 | rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, |
1613 | val: mcs_b + power_base->reg_084c); |
1614 | |
1615 | rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, |
1616 | val: mcs_a + power_base->reg_0e1c); |
1617 | for (i = 0; i < 3; i++) { |
1618 | if (i != 2) |
1619 | val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0; |
1620 | else |
1621 | val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0; |
1622 | rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val: val8); |
1623 | } |
1624 | rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, |
1625 | val: mcs_b + power_base->reg_0868); |
1626 | for (i = 0; i < 3; i++) { |
1627 | if (i != 2) |
1628 | val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0; |
1629 | else |
1630 | val8 = (mcsbase[1] > 6) ? (mcsbase[1] - 6) : 0; |
1631 | rtl8xxxu_write8(priv, REG_OFDM0_XD_TX_IQ_IMBALANCE + i, val: val8); |
1632 | } |
1633 | } |
1634 | |
1635 | static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, |
1636 | enum nl80211_iftype linktype, int port_num) |
1637 | { |
1638 | u8 val8, type; |
1639 | |
1640 | switch (linktype) { |
1641 | case NL80211_IFTYPE_UNSPECIFIED: |
1642 | type = MSR_LINKTYPE_NONE; |
1643 | break; |
1644 | case NL80211_IFTYPE_ADHOC: |
1645 | type = MSR_LINKTYPE_ADHOC; |
1646 | break; |
1647 | case NL80211_IFTYPE_STATION: |
1648 | type = MSR_LINKTYPE_STATION; |
1649 | break; |
1650 | case NL80211_IFTYPE_AP: |
1651 | type = MSR_LINKTYPE_AP; |
1652 | break; |
1653 | default: |
1654 | return; |
1655 | } |
1656 | |
1657 | switch (port_num) { |
1658 | case 0: |
1659 | val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x0c; |
1660 | val8 |= type; |
1661 | break; |
1662 | case 1: |
1663 | val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x03; |
1664 | val8 |= type << 2; |
1665 | break; |
1666 | default: |
1667 | return; |
1668 | } |
1669 | |
1670 | rtl8xxxu_write8(priv, REG_MSR, val: val8); |
1671 | } |
1672 | |
1673 | static void |
1674 | rtl8xxxu_set_retry(struct rtl8xxxu_priv *priv, u16 short_retry, u16 long_retry) |
1675 | { |
1676 | u16 val16; |
1677 | |
1678 | val16 = ((short_retry << RETRY_LIMIT_SHORT_SHIFT) & |
1679 | RETRY_LIMIT_SHORT_MASK) | |
1680 | ((long_retry << RETRY_LIMIT_LONG_SHIFT) & |
1681 | RETRY_LIMIT_LONG_MASK); |
1682 | |
1683 | rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val: val16); |
1684 | } |
1685 | |
1686 | static void |
1687 | rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm) |
1688 | { |
1689 | u16 val16; |
1690 | |
1691 | val16 = ((cck << SPEC_SIFS_CCK_SHIFT) & SPEC_SIFS_CCK_MASK) | |
1692 | ((ofdm << SPEC_SIFS_OFDM_SHIFT) & SPEC_SIFS_OFDM_MASK); |
1693 | |
1694 | rtl8xxxu_write16(priv, REG_SPEC_SIFS, val: val16); |
1695 | } |
1696 | |
1697 | static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) |
1698 | { |
1699 | struct device *dev = &priv->udev->dev; |
1700 | char cut = 'A' + priv->chip_cut; |
1701 | |
1702 | dev_info(dev, |
1703 | "RTL%s rev %c (%s) romver %d, %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n" , |
1704 | priv->chip_name, cut, priv->chip_vendor, priv->rom_rev, |
1705 | priv->tx_paths, priv->rx_paths, priv->ep_tx_count, |
1706 | priv->has_wifi, priv->has_bluetooth, priv->has_gps, |
1707 | priv->hi_pa); |
1708 | |
1709 | dev_info(dev, "RTL%s MAC: %pM\n" , priv->chip_name, priv->mac_addr); |
1710 | } |
1711 | |
1712 | void rtl8xxxu_identify_vendor_1bit(struct rtl8xxxu_priv *priv, u32 vendor) |
1713 | { |
1714 | if (vendor) { |
1715 | strscpy(priv->chip_vendor, "UMC" , sizeof(priv->chip_vendor)); |
1716 | priv->vendor_umc = 1; |
1717 | } else { |
1718 | strscpy(priv->chip_vendor, "TSMC" , sizeof(priv->chip_vendor)); |
1719 | } |
1720 | } |
1721 | |
1722 | void rtl8xxxu_identify_vendor_2bits(struct rtl8xxxu_priv *priv, u32 vendor) |
1723 | { |
1724 | switch (vendor) { |
1725 | case SYS_CFG_VENDOR_ID_TSMC: |
1726 | strscpy(priv->chip_vendor, "TSMC" , sizeof(priv->chip_vendor)); |
1727 | break; |
1728 | case SYS_CFG_VENDOR_ID_SMIC: |
1729 | strscpy(priv->chip_vendor, "SMIC" , sizeof(priv->chip_vendor)); |
1730 | priv->vendor_smic = 1; |
1731 | break; |
1732 | case SYS_CFG_VENDOR_ID_UMC: |
1733 | strscpy(priv->chip_vendor, "UMC" , sizeof(priv->chip_vendor)); |
1734 | priv->vendor_umc = 1; |
1735 | break; |
1736 | default: |
1737 | strscpy(priv->chip_vendor, "unknown" , sizeof(priv->chip_vendor)); |
1738 | } |
1739 | } |
1740 | |
1741 | void rtl8xxxu_config_endpoints_sie(struct rtl8xxxu_priv *priv) |
1742 | { |
1743 | u16 val16; |
1744 | |
1745 | val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX); |
1746 | |
1747 | if (val16 & NORMAL_SIE_EP_TX_HIGH_MASK) { |
1748 | priv->ep_tx_high_queue = 1; |
1749 | priv->ep_tx_count++; |
1750 | } |
1751 | |
1752 | if (val16 & NORMAL_SIE_EP_TX_NORMAL_MASK) { |
1753 | priv->ep_tx_normal_queue = 1; |
1754 | priv->ep_tx_count++; |
1755 | } |
1756 | |
1757 | if (val16 & NORMAL_SIE_EP_TX_LOW_MASK) { |
1758 | priv->ep_tx_low_queue = 1; |
1759 | priv->ep_tx_count++; |
1760 | } |
1761 | } |
1762 | |
1763 | int rtl8xxxu_config_endpoints_no_sie(struct rtl8xxxu_priv *priv) |
1764 | { |
1765 | struct device *dev = &priv->udev->dev; |
1766 | |
1767 | switch (priv->nr_out_eps) { |
1768 | case 6: |
1769 | case 5: |
1770 | case 4: |
1771 | case 3: |
1772 | priv->ep_tx_low_queue = 1; |
1773 | priv->ep_tx_count++; |
1774 | fallthrough; |
1775 | case 2: |
1776 | priv->ep_tx_normal_queue = 1; |
1777 | priv->ep_tx_count++; |
1778 | fallthrough; |
1779 | case 1: |
1780 | priv->ep_tx_high_queue = 1; |
1781 | priv->ep_tx_count++; |
1782 | break; |
1783 | default: |
1784 | dev_info(dev, "Unsupported USB TX end-points\n" ); |
1785 | return -ENOTSUPP; |
1786 | } |
1787 | |
1788 | return 0; |
1789 | } |
1790 | |
1791 | int |
1792 | rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data) |
1793 | { |
1794 | int i; |
1795 | u8 val8; |
1796 | u32 val32; |
1797 | |
1798 | /* Write Address */ |
1799 | rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 1, val: offset & 0xff); |
1800 | val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 2); |
1801 | val8 &= 0xfc; |
1802 | val8 |= (offset >> 8) & 0x03; |
1803 | rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 2, val: val8); |
1804 | |
1805 | val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 3); |
1806 | rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 3, val: val8 & 0x7f); |
1807 | |
1808 | /* Poll for data read */ |
1809 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); |
1810 | for (i = 0; i < RTL8XXXU_MAX_REG_POLL; i++) { |
1811 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); |
1812 | if (val32 & BIT(31)) |
1813 | break; |
1814 | } |
1815 | |
1816 | if (i == RTL8XXXU_MAX_REG_POLL) |
1817 | return -EIO; |
1818 | |
1819 | udelay(50); |
1820 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); |
1821 | |
1822 | *data = val32 & 0xff; |
1823 | return 0; |
1824 | } |
1825 | |
1826 | int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) |
1827 | { |
1828 | struct device *dev = &priv->udev->dev; |
1829 | int i, ret = 0; |
1830 | u8 val8, word_mask, , ; |
1831 | u16 val16, efuse_addr, offset; |
1832 | u32 val32; |
1833 | |
1834 | val16 = rtl8xxxu_read16(priv, REG_9346CR); |
1835 | if (val16 & EEPROM_ENABLE) |
1836 | priv->has_eeprom = 1; |
1837 | if (val16 & EEPROM_BOOT) |
1838 | priv->boot_eeprom = 1; |
1839 | |
1840 | if (priv->is_multi_func) { |
1841 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST); |
1842 | val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT; |
1843 | rtl8xxxu_write32(priv, REG_EFUSE_TEST, val: val32); |
1844 | } |
1845 | |
1846 | dev_dbg(dev, "Booting from %s\n" , |
1847 | priv->boot_eeprom ? "EEPROM" : "EFUSE" ); |
1848 | |
1849 | rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_ENABLE); |
1850 | |
1851 | /* 1.2V Power: From VDDON with Power Cut(0x0000[15]), default valid */ |
1852 | val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL); |
1853 | if (!(val16 & SYS_ISO_PWC_EV12V)) { |
1854 | val16 |= SYS_ISO_PWC_EV12V; |
1855 | rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val: val16); |
1856 | } |
1857 | /* Reset: 0x0000[28], default valid */ |
1858 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
1859 | if (!(val16 & SYS_FUNC_ELDR)) { |
1860 | val16 |= SYS_FUNC_ELDR; |
1861 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: val16); |
1862 | } |
1863 | |
1864 | /* |
1865 | * Clock: Gated(0x0008[5]) 8M(0x0008[1]) clock from ANA, default valid |
1866 | */ |
1867 | val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); |
1868 | if (!(val16 & SYS_CLK_LOADER_ENABLE) || !(val16 & SYS_CLK_ANA8M)) { |
1869 | val16 |= (SYS_CLK_LOADER_ENABLE | SYS_CLK_ANA8M); |
1870 | rtl8xxxu_write16(priv, REG_SYS_CLKR, val: val16); |
1871 | } |
1872 | |
1873 | /* Default value is 0xff */ |
1874 | memset(priv->efuse_wifi.raw, 0xff, EFUSE_MAP_LEN); |
1875 | |
1876 | efuse_addr = 0; |
1877 | while (efuse_addr < EFUSE_REAL_CONTENT_LEN_8723A) { |
1878 | u16 map_addr; |
1879 | |
1880 | ret = rtl8xxxu_read_efuse8(priv, offset: efuse_addr++, data: &header); |
1881 | if (ret || header == 0xff) |
1882 | goto exit; |
1883 | |
1884 | if ((header & 0x1f) == 0x0f) { /* extended header */ |
1885 | offset = (header & 0xe0) >> 5; |
1886 | |
1887 | ret = rtl8xxxu_read_efuse8(priv, offset: efuse_addr++, |
1888 | data: &extheader); |
1889 | if (ret) |
1890 | goto exit; |
1891 | /* All words disabled */ |
1892 | if ((extheader & 0x0f) == 0x0f) |
1893 | continue; |
1894 | |
1895 | offset |= ((extheader & 0xf0) >> 1); |
1896 | word_mask = extheader & 0x0f; |
1897 | } else { |
1898 | offset = (header >> 4) & 0x0f; |
1899 | word_mask = header & 0x0f; |
1900 | } |
1901 | |
1902 | /* Get word enable value from PG header */ |
1903 | |
1904 | /* We have 8 bits to indicate validity */ |
1905 | map_addr = offset * 8; |
1906 | for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { |
1907 | /* Check word enable condition in the section */ |
1908 | if (word_mask & BIT(i)) { |
1909 | map_addr += 2; |
1910 | continue; |
1911 | } |
1912 | |
1913 | ret = rtl8xxxu_read_efuse8(priv, offset: efuse_addr++, data: &val8); |
1914 | if (ret) |
1915 | goto exit; |
1916 | if (map_addr >= EFUSE_MAP_LEN - 1) { |
1917 | dev_warn(dev, "%s: Illegal map_addr (%04x), " |
1918 | "efuse corrupt!\n" , |
1919 | __func__, map_addr); |
1920 | ret = -EINVAL; |
1921 | goto exit; |
1922 | } |
1923 | priv->efuse_wifi.raw[map_addr++] = val8; |
1924 | |
1925 | ret = rtl8xxxu_read_efuse8(priv, offset: efuse_addr++, data: &val8); |
1926 | if (ret) |
1927 | goto exit; |
1928 | priv->efuse_wifi.raw[map_addr++] = val8; |
1929 | } |
1930 | } |
1931 | |
1932 | exit: |
1933 | rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_DISABLE); |
1934 | |
1935 | return ret; |
1936 | } |
1937 | |
1938 | static void rtl8xxxu_dump_efuse(struct rtl8xxxu_priv *priv) |
1939 | { |
1940 | dev_info(&priv->udev->dev, |
1941 | "Dumping efuse for RTL%s (0x%02x bytes):\n" , |
1942 | priv->chip_name, EFUSE_MAP_LEN); |
1943 | |
1944 | print_hex_dump(KERN_INFO, prefix_str: "" , prefix_type: DUMP_PREFIX_OFFSET, rowsize: 16, groupsize: 1, |
1945 | buf: priv->efuse_wifi.raw, EFUSE_MAP_LEN, ascii: true); |
1946 | } |
1947 | |
1948 | void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv) |
1949 | { |
1950 | u8 val8; |
1951 | u16 sys_func; |
1952 | |
1953 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); |
1954 | val8 &= ~BIT(0); |
1955 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val: val8); |
1956 | |
1957 | sys_func = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
1958 | sys_func &= ~SYS_FUNC_CPU_ENABLE; |
1959 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: sys_func); |
1960 | |
1961 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); |
1962 | val8 |= BIT(0); |
1963 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val: val8); |
1964 | |
1965 | sys_func |= SYS_FUNC_CPU_ENABLE; |
1966 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: sys_func); |
1967 | } |
1968 | |
1969 | static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) |
1970 | { |
1971 | struct device *dev = &priv->udev->dev; |
1972 | u16 reg_mcu_fw_dl; |
1973 | int ret = 0, i; |
1974 | u32 val32; |
1975 | |
1976 | if (priv->rtl_chip == RTL8710B) |
1977 | reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B; |
1978 | else |
1979 | reg_mcu_fw_dl = REG_MCU_FW_DL; |
1980 | |
1981 | /* Poll checksum report */ |
1982 | for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { |
1983 | val32 = rtl8xxxu_read32(priv, addr: reg_mcu_fw_dl); |
1984 | if (val32 & MCU_FW_DL_CSUM_REPORT) |
1985 | break; |
1986 | } |
1987 | |
1988 | if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { |
1989 | dev_warn(dev, "Firmware checksum poll timed out\n" ); |
1990 | ret = -EAGAIN; |
1991 | goto exit; |
1992 | } |
1993 | |
1994 | val32 = rtl8xxxu_read32(priv, addr: reg_mcu_fw_dl); |
1995 | val32 |= MCU_FW_DL_READY; |
1996 | val32 &= ~MCU_WINT_INIT_READY; |
1997 | rtl8xxxu_write32(priv, addr: reg_mcu_fw_dl, val: val32); |
1998 | |
1999 | /* |
2000 | * Reset the 8051 in order for the firmware to start running, |
2001 | * otherwise it won't come up on the 8192eu |
2002 | */ |
2003 | priv->fops->reset_8051(priv); |
2004 | |
2005 | /* Wait for firmware to become ready */ |
2006 | for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { |
2007 | val32 = rtl8xxxu_read32(priv, addr: reg_mcu_fw_dl); |
2008 | if (val32 & MCU_WINT_INIT_READY) |
2009 | break; |
2010 | |
2011 | udelay(100); |
2012 | } |
2013 | |
2014 | if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { |
2015 | dev_warn(dev, "Firmware failed to start\n" ); |
2016 | ret = -EAGAIN; |
2017 | goto exit; |
2018 | } |
2019 | |
2020 | /* |
2021 | * Init H2C command |
2022 | */ |
2023 | if (priv->fops->init_reg_hmtfr) |
2024 | rtl8xxxu_write8(priv, REG_HMTFR, val: 0x0f); |
2025 | exit: |
2026 | return ret; |
2027 | } |
2028 | |
2029 | static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) |
2030 | { |
2031 | int pages, remainder, i, ret; |
2032 | u16 reg_fw_start_address; |
2033 | u16 reg_mcu_fw_dl; |
2034 | u8 val8; |
2035 | u16 val16; |
2036 | u32 val32; |
2037 | u8 *fwptr; |
2038 | |
2039 | if (priv->rtl_chip == RTL8192F) |
2040 | reg_fw_start_address = REG_FW_START_ADDRESS_8192F; |
2041 | else |
2042 | reg_fw_start_address = REG_FW_START_ADDRESS; |
2043 | |
2044 | if (priv->rtl_chip == RTL8710B) { |
2045 | reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B; |
2046 | } else { |
2047 | reg_mcu_fw_dl = REG_MCU_FW_DL; |
2048 | |
2049 | val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1); |
2050 | val8 |= 4; |
2051 | rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val: val8); |
2052 | |
2053 | /* 8051 enable */ |
2054 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
2055 | val16 |= SYS_FUNC_CPU_ENABLE; |
2056 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: val16); |
2057 | } |
2058 | |
2059 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl); |
2060 | if (val8 & MCU_FW_RAM_SEL) { |
2061 | dev_info(&priv->udev->dev, |
2062 | "Firmware is already running, resetting the MCU.\n" ); |
2063 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl, val: 0x00); |
2064 | priv->fops->reset_8051(priv); |
2065 | } |
2066 | |
2067 | /* MCU firmware download enable */ |
2068 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl); |
2069 | val8 |= MCU_FW_DL_ENABLE; |
2070 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl, val: val8); |
2071 | |
2072 | /* 8051 reset */ |
2073 | val32 = rtl8xxxu_read32(priv, addr: reg_mcu_fw_dl); |
2074 | val32 &= ~BIT(19); |
2075 | rtl8xxxu_write32(priv, addr: reg_mcu_fw_dl, val: val32); |
2076 | |
2077 | if (priv->rtl_chip == RTL8710B) { |
2078 | /* We must set 0x8090[8]=1 before download FW. */ |
2079 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl + 1); |
2080 | val8 |= BIT(0); |
2081 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl + 1, val: val8); |
2082 | } |
2083 | |
2084 | /* Reset firmware download checksum */ |
2085 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl); |
2086 | val8 |= MCU_FW_DL_CSUM_REPORT; |
2087 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl, val: val8); |
2088 | |
2089 | pages = priv->fw_size / RTL_FW_PAGE_SIZE; |
2090 | remainder = priv->fw_size % RTL_FW_PAGE_SIZE; |
2091 | |
2092 | fwptr = priv->fw_data->data; |
2093 | |
2094 | for (i = 0; i < pages; i++) { |
2095 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl + 2) & 0xF8; |
2096 | val8 |= i; |
2097 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl + 2, val: val8); |
2098 | |
2099 | ret = rtl8xxxu_writeN(priv, addr: reg_fw_start_address, |
2100 | buf: fwptr, RTL_FW_PAGE_SIZE); |
2101 | if (ret != RTL_FW_PAGE_SIZE) { |
2102 | ret = -EAGAIN; |
2103 | goto fw_abort; |
2104 | } |
2105 | |
2106 | fwptr += RTL_FW_PAGE_SIZE; |
2107 | } |
2108 | |
2109 | if (remainder) { |
2110 | val8 = rtl8xxxu_read8(priv, addr: reg_mcu_fw_dl + 2) & 0xF8; |
2111 | val8 |= i; |
2112 | rtl8xxxu_write8(priv, addr: reg_mcu_fw_dl + 2, val: val8); |
2113 | ret = rtl8xxxu_writeN(priv, addr: reg_fw_start_address, |
2114 | buf: fwptr, len: remainder); |
2115 | if (ret != remainder) { |
2116 | ret = -EAGAIN; |
2117 | goto fw_abort; |
2118 | } |
2119 | } |
2120 | |
2121 | ret = 0; |
2122 | fw_abort: |
2123 | /* MCU firmware download disable */ |
2124 | val16 = rtl8xxxu_read16(priv, addr: reg_mcu_fw_dl); |
2125 | val16 &= ~MCU_FW_DL_ENABLE; |
2126 | rtl8xxxu_write16(priv, addr: reg_mcu_fw_dl, val: val16); |
2127 | |
2128 | return ret; |
2129 | } |
2130 | |
2131 | int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name) |
2132 | { |
2133 | struct device *dev = &priv->udev->dev; |
2134 | const struct firmware *fw; |
2135 | int ret = 0; |
2136 | u16 signature; |
2137 | |
2138 | dev_info(dev, "%s: Loading firmware %s\n" , DRIVER_NAME, fw_name); |
2139 | if (request_firmware(fw: &fw, name: fw_name, device: &priv->udev->dev)) { |
2140 | dev_warn(dev, "request_firmware(%s) failed\n" , fw_name); |
2141 | ret = -EAGAIN; |
2142 | goto exit; |
2143 | } |
2144 | if (!fw) { |
2145 | dev_warn(dev, "Firmware data not available\n" ); |
2146 | ret = -EINVAL; |
2147 | goto exit; |
2148 | } |
2149 | |
2150 | priv->fw_data = kmemdup(p: fw->data, size: fw->size, GFP_KERNEL); |
2151 | if (!priv->fw_data) { |
2152 | ret = -ENOMEM; |
2153 | goto exit; |
2154 | } |
2155 | priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header); |
2156 | |
2157 | signature = le16_to_cpu(priv->fw_data->signature); |
2158 | switch (signature & 0xfff0) { |
2159 | case 0x92e0: |
2160 | case 0x92c0: |
2161 | case 0x88e0: |
2162 | case 0x88c0: |
2163 | case 0x5300: |
2164 | case 0x2300: |
2165 | case 0x88f0: |
2166 | case 0x10b0: |
2167 | case 0x92f0: |
2168 | break; |
2169 | default: |
2170 | ret = -EINVAL; |
2171 | dev_warn(dev, "%s: Invalid firmware signature: 0x%04x\n" , |
2172 | __func__, signature); |
2173 | } |
2174 | |
2175 | dev_info(dev, "Firmware revision %i.%i (signature 0x%04x)\n" , |
2176 | le16_to_cpu(priv->fw_data->major_version), |
2177 | priv->fw_data->minor_version, signature); |
2178 | |
2179 | exit: |
2180 | release_firmware(fw); |
2181 | return ret; |
2182 | } |
2183 | |
2184 | void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv) |
2185 | { |
2186 | u16 val16; |
2187 | int i = 100; |
2188 | |
2189 | /* Inform 8051 to perform reset */ |
2190 | rtl8xxxu_write8(priv, REG_HMTFR + 3, val: 0x20); |
2191 | |
2192 | for (i = 100; i > 0; i--) { |
2193 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
2194 | |
2195 | if (!(val16 & SYS_FUNC_CPU_ENABLE)) { |
2196 | dev_dbg(&priv->udev->dev, |
2197 | "%s: Firmware self reset success!\n" , __func__); |
2198 | break; |
2199 | } |
2200 | udelay(50); |
2201 | } |
2202 | |
2203 | if (!i) { |
2204 | /* Force firmware reset */ |
2205 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
2206 | val16 &= ~SYS_FUNC_CPU_ENABLE; |
2207 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: val16); |
2208 | } |
2209 | } |
2210 | |
2211 | static int |
2212 | rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv) |
2213 | { |
2214 | const struct rtl8xxxu_reg8val *array = priv->fops->mactable; |
2215 | int i, ret; |
2216 | u16 reg; |
2217 | u8 val; |
2218 | |
2219 | for (i = 0; ; i++) { |
2220 | reg = array[i].reg; |
2221 | val = array[i].val; |
2222 | |
2223 | if (reg == 0xffff && val == 0xff) |
2224 | break; |
2225 | |
2226 | ret = rtl8xxxu_write8(priv, addr: reg, val); |
2227 | if (ret != 1) { |
2228 | dev_warn(&priv->udev->dev, |
2229 | "Failed to initialize MAC " |
2230 | "(reg: %04x, val %02x)\n" , reg, val); |
2231 | return -EAGAIN; |
2232 | } |
2233 | } |
2234 | |
2235 | switch (priv->rtl_chip) { |
2236 | case RTL8188C: |
2237 | case RTL8188R: |
2238 | case RTL8191C: |
2239 | case RTL8192C: |
2240 | case RTL8723A: |
2241 | rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, val: 0x0a); |
2242 | break; |
2243 | case RTL8188E: |
2244 | rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, val: 0x0707); |
2245 | break; |
2246 | default: |
2247 | break; |
2248 | } |
2249 | |
2250 | return 0; |
2251 | } |
2252 | |
2253 | int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, |
2254 | const struct rtl8xxxu_reg32val *array) |
2255 | { |
2256 | int i, ret; |
2257 | u16 reg; |
2258 | u32 val; |
2259 | |
2260 | for (i = 0; ; i++) { |
2261 | reg = array[i].reg; |
2262 | val = array[i].val; |
2263 | |
2264 | if (reg == 0xffff && val == 0xffffffff) |
2265 | break; |
2266 | |
2267 | ret = rtl8xxxu_write32(priv, addr: reg, val); |
2268 | if (ret != sizeof(val)) { |
2269 | dev_warn(&priv->udev->dev, |
2270 | "Failed to initialize PHY\n" ); |
2271 | return -EAGAIN; |
2272 | } |
2273 | udelay(1); |
2274 | } |
2275 | |
2276 | return 0; |
2277 | } |
2278 | |
2279 | void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv) |
2280 | { |
2281 | u8 val8, ldoa15, ldov12d, lpldo, ldohci12; |
2282 | u16 val16; |
2283 | u32 val32; |
2284 | |
2285 | val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); |
2286 | udelay(2); |
2287 | val8 |= AFE_PLL_320_ENABLE; |
2288 | rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val: val8); |
2289 | udelay(2); |
2290 | |
2291 | rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, val: 0xff); |
2292 | udelay(2); |
2293 | |
2294 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
2295 | val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; |
2296 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: val16); |
2297 | |
2298 | val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); |
2299 | val32 &= ~AFE_XTAL_RF_GATE; |
2300 | if (priv->has_bluetooth) |
2301 | val32 &= ~AFE_XTAL_BT_GATE; |
2302 | rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val: val32); |
2303 | |
2304 | /* 6. 0x1f[7:0] = 0x07 */ |
2305 | val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; |
2306 | rtl8xxxu_write8(priv, REG_RF_CTRL, val: val8); |
2307 | |
2308 | if (priv->hi_pa) |
2309 | rtl8xxxu_init_phy_regs(priv, array: rtl8188ru_phy_1t_highpa_table); |
2310 | else if (priv->tx_paths == 2) |
2311 | rtl8xxxu_init_phy_regs(priv, array: rtl8192cu_phy_2t_init_table); |
2312 | else |
2313 | rtl8xxxu_init_phy_regs(priv, array: rtl8723a_phy_1t_init_table); |
2314 | |
2315 | if (priv->rtl_chip == RTL8188R && priv->hi_pa && |
2316 | priv->vendor_umc && priv->chip_cut == 1) |
2317 | rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, val: 0x50); |
2318 | |
2319 | if (priv->hi_pa) |
2320 | rtl8xxxu_init_phy_regs(priv, array: rtl8xxx_agc_highpa_table); |
2321 | else |
2322 | rtl8xxxu_init_phy_regs(priv, array: rtl8xxx_agc_standard_table); |
2323 | |
2324 | ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; |
2325 | ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); |
2326 | ldohci12 = 0x57; |
2327 | lpldo = 1; |
2328 | val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15; |
2329 | rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val: val32); |
2330 | } |
2331 | |
2332 | /* |
2333 | * Most of this is black magic retrieved from the old rtl8723au driver |
2334 | */ |
2335 | static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) |
2336 | { |
2337 | u32 val32; |
2338 | |
2339 | priv->fops->init_phy_bb(priv); |
2340 | |
2341 | if (priv->tx_paths == 1 && priv->rx_paths == 2) { |
2342 | /* |
2343 | * For 1T2R boards, patch the registers. |
2344 | * |
2345 | * It looks like 8191/2 1T2R boards use path B for TX |
2346 | */ |
2347 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_TX_INFO); |
2348 | val32 &= ~(BIT(0) | BIT(1)); |
2349 | val32 |= BIT(1); |
2350 | rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, val: val32); |
2351 | |
2352 | val32 = rtl8xxxu_read32(priv, REG_FPGA1_TX_INFO); |
2353 | val32 &= ~0x300033; |
2354 | val32 |= 0x200022; |
2355 | rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val: val32); |
2356 | |
2357 | val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); |
2358 | val32 &= ~CCK0_AFE_RX_MASK; |
2359 | val32 &= 0x00ffffff; |
2360 | val32 |= 0x40000000; |
2361 | val32 |= CCK0_AFE_RX_ANT_B; |
2362 | rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val: val32); |
2363 | |
2364 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); |
2365 | val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK); |
2366 | val32 |= (OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B | |
2367 | OFDM_RF_PATH_TX_B); |
2368 | rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val: val32); |
2369 | |
2370 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_PARM1); |
2371 | val32 &= ~(BIT(4) | BIT(5)); |
2372 | val32 |= BIT(4); |
2373 | rtl8xxxu_write32(priv, REG_OFDM0_AGC_PARM1, val: val32); |
2374 | |
2375 | val32 = rtl8xxxu_read32(priv, REG_TX_CCK_RFON); |
2376 | val32 &= ~(BIT(27) | BIT(26)); |
2377 | val32 |= BIT(27); |
2378 | rtl8xxxu_write32(priv, REG_TX_CCK_RFON, val: val32); |
2379 | |
2380 | val32 = rtl8xxxu_read32(priv, REG_TX_CCK_BBON); |
2381 | val32 &= ~(BIT(27) | BIT(26)); |
2382 | val32 |= BIT(27); |
2383 | rtl8xxxu_write32(priv, REG_TX_CCK_BBON, val: val32); |
2384 | |
2385 | val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_RFON); |
2386 | val32 &= ~(BIT(27) | BIT(26)); |
2387 | val32 |= BIT(27); |
2388 | rtl8xxxu_write32(priv, REG_TX_OFDM_RFON, val: val32); |
2389 | |
2390 | val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_BBON); |
2391 | val32 &= ~(BIT(27) | BIT(26)); |
2392 | val32 |= BIT(27); |
2393 | rtl8xxxu_write32(priv, REG_TX_OFDM_BBON, val: val32); |
2394 | |
2395 | val32 = rtl8xxxu_read32(priv, REG_TX_TO_TX); |
2396 | val32 &= ~(BIT(27) | BIT(26)); |
2397 | val32 |= BIT(27); |
2398 | rtl8xxxu_write32(priv, REG_TX_TO_TX, val: val32); |
2399 | } |
2400 | |
2401 | if (priv->fops->set_crystal_cap) |
2402 | priv->fops->set_crystal_cap(priv, priv->default_crystal_cap); |
2403 | |
2404 | if (priv->rtl_chip == RTL8192E) |
2405 | rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val: 0x000f81fb); |
2406 | |
2407 | return 0; |
2408 | } |
2409 | |
2410 | static int rtl8xxxu_init_rf_regs(struct rtl8xxxu_priv *priv, |
2411 | const struct rtl8xxxu_rfregval *array, |
2412 | enum rtl8xxxu_rfpath path) |
2413 | { |
2414 | int i, ret; |
2415 | u8 reg; |
2416 | u32 val; |
2417 | |
2418 | for (i = 0; ; i++) { |
2419 | reg = array[i].reg; |
2420 | val = array[i].val; |
2421 | |
2422 | if (reg == 0xff && val == 0xffffffff) |
2423 | break; |
2424 | |
2425 | switch (reg) { |
2426 | case 0xfe: |
2427 | msleep(msecs: 50); |
2428 | continue; |
2429 | case 0xfd: |
2430 | mdelay(5); |
2431 | continue; |
2432 | case 0xfc: |
2433 | mdelay(1); |
2434 | continue; |
2435 | case 0xfb: |
2436 | udelay(50); |
2437 | continue; |
2438 | case 0xfa: |
2439 | udelay(5); |
2440 | continue; |
2441 | case 0xf9: |
2442 | udelay(1); |
2443 | continue; |
2444 | } |
2445 | |
2446 | ret = rtl8xxxu_write_rfreg(priv, path, reg, data: val); |
2447 | if (ret) { |
2448 | dev_warn(&priv->udev->dev, |
2449 | "Failed to initialize RF\n" ); |
2450 | return -EAGAIN; |
2451 | } |
2452 | udelay(1); |
2453 | } |
2454 | |
2455 | return 0; |
2456 | } |
2457 | |
2458 | int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv, |
2459 | const struct rtl8xxxu_rfregval *table, |
2460 | enum rtl8xxxu_rfpath path) |
2461 | { |
2462 | u32 val32; |
2463 | u16 val16, rfsi_rfenv; |
2464 | u16 reg_sw_ctrl, reg_int_oe, reg_hssi_parm2; |
2465 | |
2466 | switch (path) { |
2467 | case RF_A: |
2468 | reg_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL; |
2469 | reg_int_oe = REG_FPGA0_XA_RF_INT_OE; |
2470 | reg_hssi_parm2 = REG_FPGA0_XA_HSSI_PARM2; |
2471 | break; |
2472 | case RF_B: |
2473 | reg_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL; |
2474 | reg_int_oe = REG_FPGA0_XB_RF_INT_OE; |
2475 | reg_hssi_parm2 = REG_FPGA0_XB_HSSI_PARM2; |
2476 | break; |
2477 | default: |
2478 | dev_err(&priv->udev->dev, "%s:Unsupported RF path %c\n" , |
2479 | __func__, path + 'A'); |
2480 | return -EINVAL; |
2481 | } |
2482 | /* For path B, use XB */ |
2483 | rfsi_rfenv = rtl8xxxu_read16(priv, addr: reg_sw_ctrl); |
2484 | rfsi_rfenv &= FPGA0_RF_RFENV; |
2485 | |
2486 | /* |
2487 | * These two we might be able to optimize into one |
2488 | */ |
2489 | val32 = rtl8xxxu_read32(priv, addr: reg_int_oe); |
2490 | val32 |= BIT(20); /* 0x10 << 16 */ |
2491 | rtl8xxxu_write32(priv, addr: reg_int_oe, val: val32); |
2492 | udelay(1); |
2493 | |
2494 | val32 = rtl8xxxu_read32(priv, addr: reg_int_oe); |
2495 | val32 |= BIT(4); |
2496 | rtl8xxxu_write32(priv, addr: reg_int_oe, val: val32); |
2497 | udelay(1); |
2498 | |
2499 | /* |
2500 | * These two we might be able to optimize into one |
2501 | */ |
2502 | val32 = rtl8xxxu_read32(priv, addr: reg_hssi_parm2); |
2503 | val32 &= ~FPGA0_HSSI_3WIRE_ADDR_LEN; |
2504 | rtl8xxxu_write32(priv, addr: reg_hssi_parm2, val: val32); |
2505 | udelay(1); |
2506 | |
2507 | val32 = rtl8xxxu_read32(priv, addr: reg_hssi_parm2); |
2508 | val32 &= ~FPGA0_HSSI_3WIRE_DATA_LEN; |
2509 | rtl8xxxu_write32(priv, addr: reg_hssi_parm2, val: val32); |
2510 | udelay(1); |
2511 | |
2512 | rtl8xxxu_init_rf_regs(priv, array: table, path); |
2513 | |
2514 | /* For path B, use XB */ |
2515 | val16 = rtl8xxxu_read16(priv, addr: reg_sw_ctrl); |
2516 | val16 &= ~FPGA0_RF_RFENV; |
2517 | val16 |= rfsi_rfenv; |
2518 | rtl8xxxu_write16(priv, addr: reg_sw_ctrl, val: val16); |
2519 | |
2520 | return 0; |
2521 | } |
2522 | |
2523 | static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data) |
2524 | { |
2525 | int ret = -EBUSY; |
2526 | int count = 0; |
2527 | u32 value; |
2528 | |
2529 | value = LLT_OP_WRITE | address << 8 | data; |
2530 | |
2531 | rtl8xxxu_write32(priv, REG_LLT_INIT, val: value); |
2532 | |
2533 | do { |
2534 | value = rtl8xxxu_read32(priv, REG_LLT_INIT); |
2535 | if ((value & LLT_OP_MASK) == LLT_OP_INACTIVE) { |
2536 | ret = 0; |
2537 | break; |
2538 | } |
2539 | } while (count++ < 20); |
2540 | |
2541 | return ret; |
2542 | } |
2543 | |
2544 | int rtl8xxxu_init_llt_table(struct rtl8xxxu_priv *priv) |
2545 | { |
2546 | int ret; |
2547 | int i, last_entry; |
2548 | u8 last_tx_page; |
2549 | |
2550 | last_tx_page = priv->fops->total_page_num; |
2551 | |
2552 | if (priv->fops->last_llt_entry) |
2553 | last_entry = priv->fops->last_llt_entry; |
2554 | else |
2555 | last_entry = 255; |
2556 | |
2557 | for (i = 0; i < last_tx_page; i++) { |
2558 | ret = rtl8xxxu_llt_write(priv, address: i, data: i + 1); |
2559 | if (ret) |
2560 | goto exit; |
2561 | } |
2562 | |
2563 | ret = rtl8xxxu_llt_write(priv, address: last_tx_page, data: 0xff); |
2564 | if (ret) |
2565 | goto exit; |
2566 | |
2567 | /* Mark remaining pages as a ring buffer */ |
2568 | for (i = last_tx_page + 1; i < last_entry; i++) { |
2569 | ret = rtl8xxxu_llt_write(priv, address: i, data: (i + 1)); |
2570 | if (ret) |
2571 | goto exit; |
2572 | } |
2573 | |
2574 | /* Let last entry point to the start entry of ring buffer */ |
2575 | ret = rtl8xxxu_llt_write(priv, address: last_entry, data: last_tx_page + 1); |
2576 | if (ret) |
2577 | goto exit; |
2578 | |
2579 | exit: |
2580 | return ret; |
2581 | } |
2582 | |
2583 | int rtl8xxxu_auto_llt_table(struct rtl8xxxu_priv *priv) |
2584 | { |
2585 | u32 val32; |
2586 | int ret = 0; |
2587 | int i; |
2588 | |
2589 | val32 = rtl8xxxu_read32(priv, REG_AUTO_LLT); |
2590 | val32 |= AUTO_LLT_INIT_LLT; |
2591 | rtl8xxxu_write32(priv, REG_AUTO_LLT, val: val32); |
2592 | |
2593 | for (i = 500; i; i--) { |
2594 | val32 = rtl8xxxu_read32(priv, REG_AUTO_LLT); |
2595 | if (!(val32 & AUTO_LLT_INIT_LLT)) |
2596 | break; |
2597 | usleep_range(min: 2, max: 4); |
2598 | } |
2599 | |
2600 | if (!i) { |
2601 | ret = -EBUSY; |
2602 | dev_warn(&priv->udev->dev, "LLT table init failed\n" ); |
2603 | } |
2604 | |
2605 | return ret; |
2606 | } |
2607 | |
2608 | static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) |
2609 | { |
2610 | u16 val16, hi, lo; |
2611 | u16 hiq, mgq, bkq, beq, viq, voq; |
2612 | int hip, mgp, bkp, bep, vip, vop; |
2613 | int ret = 0; |
2614 | u32 val32; |
2615 | |
2616 | switch (priv->ep_tx_count) { |
2617 | case 1: |
2618 | if (priv->ep_tx_high_queue) { |
2619 | hi = TRXDMA_QUEUE_HIGH; |
2620 | } else if (priv->ep_tx_low_queue) { |
2621 | hi = TRXDMA_QUEUE_LOW; |
2622 | } else if (priv->ep_tx_normal_queue) { |
2623 | hi = TRXDMA_QUEUE_NORMAL; |
2624 | } else { |
2625 | hi = 0; |
2626 | ret = -EINVAL; |
2627 | } |
2628 | |
2629 | hiq = hi; |
2630 | mgq = hi; |
2631 | bkq = hi; |
2632 | beq = hi; |
2633 | viq = hi; |
2634 | voq = hi; |
2635 | |
2636 | hip = 0; |
2637 | mgp = 0; |
2638 | bkp = 0; |
2639 | bep = 0; |
2640 | vip = 0; |
2641 | vop = 0; |
2642 | break; |
2643 | case 2: |
2644 | if (priv->ep_tx_high_queue && priv->ep_tx_low_queue) { |
2645 | hi = TRXDMA_QUEUE_HIGH; |
2646 | lo = TRXDMA_QUEUE_LOW; |
2647 | } else if (priv->ep_tx_normal_queue && priv->ep_tx_low_queue) { |
2648 | hi = TRXDMA_QUEUE_NORMAL; |
2649 | lo = TRXDMA_QUEUE_LOW; |
2650 | } else if (priv->ep_tx_high_queue && priv->ep_tx_normal_queue) { |
2651 | hi = TRXDMA_QUEUE_HIGH; |
2652 | lo = TRXDMA_QUEUE_NORMAL; |
2653 | } else { |
2654 | ret = -EINVAL; |
2655 | hi = 0; |
2656 | lo = 0; |
2657 | } |
2658 | |
2659 | hiq = hi; |
2660 | mgq = hi; |
2661 | bkq = lo; |
2662 | beq = lo; |
2663 | viq = hi; |
2664 | voq = hi; |
2665 | |
2666 | hip = 0; |
2667 | mgp = 0; |
2668 | bkp = 1; |
2669 | bep = 1; |
2670 | vip = 0; |
2671 | vop = 0; |
2672 | break; |
2673 | case 3: |
2674 | beq = TRXDMA_QUEUE_LOW; |
2675 | bkq = TRXDMA_QUEUE_LOW; |
2676 | viq = TRXDMA_QUEUE_NORMAL; |
2677 | voq = TRXDMA_QUEUE_HIGH; |
2678 | mgq = TRXDMA_QUEUE_HIGH; |
2679 | hiq = TRXDMA_QUEUE_HIGH; |
2680 | |
2681 | hip = hiq ^ 3; |
2682 | mgp = mgq ^ 3; |
2683 | bkp = bkq ^ 3; |
2684 | bep = beq ^ 3; |
2685 | vip = viq ^ 3; |
2686 | vop = viq ^ 3; |
2687 | break; |
2688 | default: |
2689 | ret = -EINVAL; |
2690 | } |
2691 | |
2692 | /* |
2693 | * None of the vendor drivers are configuring the beacon |
2694 | * queue here .... why? |
2695 | */ |
2696 | if (!ret) { |
2697 | /* Only RTL8192F seems to do it like this. */ |
2698 | if (priv->rtl_chip == RTL8192F) { |
2699 | val32 = rtl8xxxu_read32(priv, REG_TRXDMA_CTRL); |
2700 | val32 &= 0x7; |
2701 | val32 |= (voq << TRXDMA_CTRL_VOQ_SHIFT_8192F) | |
2702 | (viq << TRXDMA_CTRL_VIQ_SHIFT_8192F) | |
2703 | (beq << TRXDMA_CTRL_BEQ_SHIFT_8192F) | |
2704 | (bkq << TRXDMA_CTRL_BKQ_SHIFT_8192F) | |
2705 | (mgq << TRXDMA_CTRL_MGQ_SHIFT_8192F) | |
2706 | (hiq << TRXDMA_CTRL_HIQ_SHIFT_8192F); |
2707 | rtl8xxxu_write32(priv, REG_TRXDMA_CTRL, val: val32); |
2708 | } else { |
2709 | val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); |
2710 | val16 &= 0x7; |
2711 | val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | |
2712 | (viq << TRXDMA_CTRL_VIQ_SHIFT) | |
2713 | (beq << TRXDMA_CTRL_BEQ_SHIFT) | |
2714 | (bkq << TRXDMA_CTRL_BKQ_SHIFT) | |
2715 | (mgq << TRXDMA_CTRL_MGQ_SHIFT) | |
2716 | (hiq << TRXDMA_CTRL_HIQ_SHIFT); |
2717 | rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val: val16); |
2718 | } |
2719 | |
2720 | priv->pipe_out[TXDESC_QUEUE_VO] = |
2721 | usb_sndbulkpipe(priv->udev, priv->out_ep[vop]); |
2722 | priv->pipe_out[TXDESC_QUEUE_VI] = |
2723 | usb_sndbulkpipe(priv->udev, priv->out_ep[vip]); |
2724 | priv->pipe_out[TXDESC_QUEUE_BE] = |
2725 | usb_sndbulkpipe(priv->udev, priv->out_ep[bep]); |
2726 | priv->pipe_out[TXDESC_QUEUE_BK] = |
2727 | usb_sndbulkpipe(priv->udev, priv->out_ep[bkp]); |
2728 | priv->pipe_out[TXDESC_QUEUE_BEACON] = |
2729 | usb_sndbulkpipe(priv->udev, priv->out_ep[0]); |
2730 | priv->pipe_out[TXDESC_QUEUE_MGNT] = |
2731 | usb_sndbulkpipe(priv->udev, priv->out_ep[mgp]); |
2732 | priv->pipe_out[TXDESC_QUEUE_HIGH] = |
2733 | usb_sndbulkpipe(priv->udev, priv->out_ep[hip]); |
2734 | priv->pipe_out[TXDESC_QUEUE_CMD] = |
2735 | usb_sndbulkpipe(priv->udev, priv->out_ep[0]); |
2736 | } |
2737 | |
2738 | return ret; |
2739 | } |
2740 | |
2741 | void rtl8xxxu_fill_iqk_matrix_a(struct rtl8xxxu_priv *priv, bool iqk_ok, |
2742 | int result[][8], int candidate, bool tx_only) |
2743 | { |
2744 | u32 oldval, x, tx0_a, reg; |
2745 | int y, tx0_c; |
2746 | u32 val32; |
2747 | |
2748 | if (!iqk_ok) |
2749 | return; |
2750 | |
2751 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); |
2752 | oldval = val32 >> 22; |
2753 | |
2754 | x = result[candidate][0]; |
2755 | if ((x & 0x00000200) != 0) |
2756 | x = x | 0xfffffc00; |
2757 | tx0_a = (x * oldval) >> 8; |
2758 | |
2759 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); |
2760 | val32 &= ~0x3ff; |
2761 | val32 |= tx0_a; |
2762 | rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val: val32); |
2763 | |
2764 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); |
2765 | val32 &= ~BIT(31); |
2766 | if ((x * oldval >> 7) & 0x1) |
2767 | val32 |= BIT(31); |
2768 | rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val: val32); |
2769 | |
2770 | y = result[candidate][1]; |
2771 | if ((y & 0x00000200) != 0) |
2772 | y = y | 0xfffffc00; |
2773 | tx0_c = (y * oldval) >> 8; |
2774 | |
2775 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XC_TX_AFE); |
2776 | val32 &= ~0xf0000000; |
2777 | val32 |= (((tx0_c & 0x3c0) >> 6) << 28); |
2778 | rtl8xxxu_write32(priv, REG_OFDM0_XC_TX_AFE, val: val32); |
2779 | |
2780 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); |
2781 | val32 &= ~0x003f0000; |
2782 | val32 |= ((tx0_c & 0x3f) << 16); |
2783 | rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val: val32); |
2784 | |
2785 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); |
2786 | val32 &= ~BIT(29); |
2787 | if ((y * oldval >> 7) & 0x1) |
2788 | val32 |= BIT(29); |
2789 | rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val: val32); |
2790 | |
2791 | if (tx_only) { |
2792 | dev_dbg(&priv->udev->dev, "%s: only TX\n" , __func__); |
2793 | return; |
2794 | } |
2795 | |
2796 | reg = result[candidate][2]; |
2797 | |
2798 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); |
2799 | val32 &= ~0x3ff; |
2800 | val32 |= (reg & 0x3ff); |
2801 | rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val: val32); |
2802 | |
2803 | reg = result[candidate][3] & 0x3F; |
2804 | |
2805 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); |
2806 | val32 &= ~0xfc00; |
2807 | val32 |= ((reg << 10) & 0xfc00); |
2808 | rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val: val32); |
2809 | |
2810 | reg = (result[candidate][3] >> 6) & 0xF; |
2811 | |
2812 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_IQ_EXT_ANTA); |
2813 | val32 &= ~0xf0000000; |
2814 | val32 |= (reg << 28); |
2815 | rtl8xxxu_write32(priv, REG_OFDM0_RX_IQ_EXT_ANTA, val: val32); |
2816 | } |
2817 | |
2818 | void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok, |
2819 | int result[][8], int candidate, bool tx_only) |
2820 | { |
2821 | u32 oldval, x, tx1_a, reg; |
2822 | int y, tx1_c; |
2823 | u32 val32; |
2824 | |
2825 | if (!iqk_ok) |
2826 | return; |
2827 | |
2828 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); |
2829 | oldval = val32 >> 22; |
2830 | |
2831 | x = result[candidate][4]; |
2832 | if ((x & 0x00000200) != 0) |
2833 | x = x | 0xfffffc00; |
2834 | tx1_a = (x * oldval) >> 8; |
2835 | |
2836 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); |
2837 | val32 &= ~0x3ff; |
2838 | val32 |= tx1_a; |
2839 | rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val: val32); |
2840 | |
2841 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); |
2842 | val32 &= ~BIT(27); |
2843 | if ((x * oldval >> 7) & 0x1) |
2844 | val32 |= BIT(27); |
2845 | rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val: val32); |
2846 | |
2847 | y = result[candidate][5]; |
2848 | if ((y & 0x00000200) != 0) |
2849 | y = y | 0xfffffc00; |
2850 | tx1_c = (y * oldval) >> 8; |
2851 | |
2852 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XD_TX_AFE); |
2853 | val32 &= ~0xf0000000; |
2854 | val32 |= (((tx1_c & 0x3c0) >> 6) << 28); |
2855 | rtl8xxxu_write32(priv, REG_OFDM0_XD_TX_AFE, val: val32); |
2856 | |
2857 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); |
2858 | val32 &= ~0x003f0000; |
2859 | val32 |= ((tx1_c & 0x3f) << 16); |
2860 | rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val: val32); |
2861 | |
2862 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); |
2863 | val32 &= ~BIT(25); |
2864 | if ((y * oldval >> 7) & 0x1) |
2865 | val32 |= BIT(25); |
2866 | rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val: val32); |
2867 | |
2868 | if (tx_only) { |
2869 | dev_dbg(&priv->udev->dev, "%s: only TX\n" , __func__); |
2870 | return; |
2871 | } |
2872 | |
2873 | reg = result[candidate][6]; |
2874 | |
2875 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); |
2876 | val32 &= ~0x3ff; |
2877 | val32 |= (reg & 0x3ff); |
2878 | rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val: val32); |
2879 | |
2880 | reg = result[candidate][7] & 0x3f; |
2881 | |
2882 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); |
2883 | val32 &= ~0xfc00; |
2884 | val32 |= ((reg << 10) & 0xfc00); |
2885 | rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val: val32); |
2886 | |
2887 | reg = (result[candidate][7] >> 6) & 0xf; |
2888 | |
2889 | if (priv->rtl_chip == RTL8192F) { |
2890 | rtl8xxxu_write32_mask(priv, REG_RXIQB_EXT, mask: 0x000000f0, val: reg); |
2891 | } else { |
2892 | val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_RSSI_TABLE); |
2893 | val32 &= ~0x0000f000; |
2894 | val32 |= (reg << 12); |
2895 | rtl8xxxu_write32(priv, REG_OFDM0_AGC_RSSI_TABLE, val: val32); |
2896 | } |
2897 | } |
2898 | |
2899 | #define MAX_TOLERANCE 5 |
2900 | |
2901 | bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv, |
2902 | int result[][8], int c1, int c2) |
2903 | { |
2904 | u32 i, j, diff, simubitmap, bound = 0; |
2905 | int candidate[2] = {-1, -1}; /* for path A and path B */ |
2906 | bool retval = true; |
2907 | |
2908 | if (priv->tx_paths > 1) |
2909 | bound = 8; |
2910 | else |
2911 | bound = 4; |
2912 | |
2913 | simubitmap = 0; |
2914 | |
2915 | for (i = 0; i < bound; i++) { |
2916 | diff = (result[c1][i] > result[c2][i]) ? |
2917 | (result[c1][i] - result[c2][i]) : |
2918 | (result[c2][i] - result[c1][i]); |
2919 | if (diff > MAX_TOLERANCE) { |
2920 | if ((i == 2 || i == 6) && !simubitmap) { |
2921 | if (result[c1][i] + result[c1][i + 1] == 0) |
2922 | candidate[(i / 4)] = c2; |
2923 | else if (result[c2][i] + result[c2][i + 1] == 0) |
2924 | candidate[(i / 4)] = c1; |
2925 | else |
2926 | simubitmap = simubitmap | (1 << i); |
2927 | } else { |
2928 | simubitmap = simubitmap | (1 << i); |
2929 | } |
2930 | } |
2931 | } |
2932 | |
2933 | if (simubitmap == 0) { |
2934 | for (i = 0; i < (bound / 4); i++) { |
2935 | if (candidate[i] >= 0) { |
2936 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) |
2937 | result[3][j] = result[candidate[i]][j]; |
2938 | retval = false; |
2939 | } |
2940 | } |
2941 | return retval; |
2942 | } else if (!(simubitmap & 0x0f)) { |
2943 | /* path A OK */ |
2944 | for (i = 0; i < 4; i++) |
2945 | result[3][i] = result[c1][i]; |
2946 | } else if (!(simubitmap & 0xf0) && priv->tx_paths > 1) { |
2947 | /* path B OK */ |
2948 | for (i = 4; i < 8; i++) |
2949 | result[3][i] = result[c1][i]; |
2950 | } |
2951 | |
2952 | return false; |
2953 | } |
2954 | |
2955 | bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, |
2956 | int result[][8], int c1, int c2) |
2957 | { |
2958 | u32 i, j, diff, simubitmap, bound = 0; |
2959 | int candidate[2] = {-1, -1}; /* for path A and path B */ |
2960 | int tmp1, tmp2; |
2961 | bool retval = true; |
2962 | |
2963 | if (priv->tx_paths > 1) |
2964 | bound = 8; |
2965 | else |
2966 | bound = 4; |
2967 | |
2968 | simubitmap = 0; |
2969 | |
2970 | for (i = 0; i < bound; i++) { |
2971 | if (i & 1) { |
2972 | if ((result[c1][i] & 0x00000200)) |
2973 | tmp1 = result[c1][i] | 0xfffffc00; |
2974 | else |
2975 | tmp1 = result[c1][i]; |
2976 | |
2977 | if ((result[c2][i]& 0x00000200)) |
2978 | tmp2 = result[c2][i] | 0xfffffc00; |
2979 | else |
2980 | tmp2 = result[c2][i]; |
2981 | } else { |
2982 | tmp1 = result[c1][i]; |
2983 | tmp2 = result[c2][i]; |
2984 | } |
2985 | |
2986 | diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1); |
2987 | |
2988 | if (diff > MAX_TOLERANCE) { |
2989 | if ((i == 2 || i == 6) && !simubitmap) { |
2990 | if (result[c1][i] + result[c1][i + 1] == 0) |
2991 | candidate[(i / 4)] = c2; |
2992 | else if (result[c2][i] + result[c2][i + 1] == 0) |
2993 | candidate[(i / 4)] = c1; |
2994 | else |
2995 | simubitmap = simubitmap | (1 << i); |
2996 | } else { |
2997 | simubitmap = simubitmap | (1 << i); |
2998 | } |
2999 | } |
3000 | } |
3001 | |
3002 | if (simubitmap == 0) { |
3003 | for (i = 0; i < (bound / 4); i++) { |
3004 | if (candidate[i] >= 0) { |
3005 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) |
3006 | result[3][j] = result[candidate[i]][j]; |
3007 | retval = false; |
3008 | } |
3009 | } |
3010 | return retval; |
3011 | } else { |
3012 | if (!(simubitmap & 0x03)) { |
3013 | /* path A TX OK */ |
3014 | for (i = 0; i < 2; i++) |
3015 | result[3][i] = result[c1][i]; |
3016 | } |
3017 | |
3018 | if (!(simubitmap & 0x0c)) { |
3019 | /* path A RX OK */ |
3020 | for (i = 2; i < 4; i++) |
3021 | result[3][i] = result[c1][i]; |
3022 | } |
3023 | |
3024 | if (!(simubitmap & 0x30) && priv->tx_paths > 1) { |
3025 | /* path B TX OK */ |
3026 | for (i = 4; i < 6; i++) |
3027 | result[3][i] = result[c1][i]; |
3028 | } |
3029 | |
3030 | if (!(simubitmap & 0xc0) && priv->tx_paths > 1) { |
3031 | /* path B RX OK */ |
3032 | for (i = 6; i < 8; i++) |
3033 | result[3][i] = result[c1][i]; |
3034 | } |
3035 | } |
3036 | |
3037 | return false; |
3038 | } |
3039 | |
3040 | void |
3041 | rtl8xxxu_save_mac_regs(struct rtl8xxxu_priv *priv, const u32 *reg, u32 *backup) |
3042 | { |
3043 | int i; |
3044 | |
3045 | for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) |
3046 | backup[i] = rtl8xxxu_read8(priv, addr: reg[i]); |
3047 | |
3048 | backup[i] = rtl8xxxu_read32(priv, addr: reg[i]); |
3049 | } |
3050 | |
3051 | void rtl8xxxu_restore_mac_regs(struct rtl8xxxu_priv *priv, |
3052 | const u32 *reg, u32 *backup) |
3053 | { |
3054 | int i; |
3055 | |
3056 | for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) |
3057 | rtl8xxxu_write8(priv, addr: reg[i], val: backup[i]); |
3058 | |
3059 | rtl8xxxu_write32(priv, addr: reg[i], val: backup[i]); |
3060 | } |
3061 | |
3062 | void rtl8xxxu_save_regs(struct rtl8xxxu_priv *priv, const u32 *regs, |
3063 | u32 *backup, int count) |
3064 | { |
3065 | int i; |
3066 | |
3067 | for (i = 0; i < count; i++) |
3068 | backup[i] = rtl8xxxu_read32(priv, addr: regs[i]); |
3069 | } |
3070 | |
3071 | void rtl8xxxu_restore_regs(struct rtl8xxxu_priv *priv, const u32 *regs, |
3072 | u32 *backup, int count) |
3073 | { |
3074 | int i; |
3075 | |
3076 | for (i = 0; i < count; i++) |
3077 | rtl8xxxu_write32(priv, addr: regs[i], val: backup[i]); |
3078 | } |
3079 | |
3080 | |
3081 | void rtl8xxxu_path_adda_on(struct rtl8xxxu_priv *priv, const u32 *regs, |
3082 | bool path_a_on) |
3083 | { |
3084 | u32 path_on; |
3085 | int i; |
3086 | |
3087 | if (priv->tx_paths == 1) { |
3088 | path_on = priv->fops->adda_1t_path_on; |
3089 | rtl8xxxu_write32(priv, addr: regs[0], val: priv->fops->adda_1t_init); |
3090 | } else { |
3091 | path_on = path_a_on ? priv->fops->adda_2t_path_on_a : |
3092 | priv->fops->adda_2t_path_on_b; |
3093 | |
3094 | rtl8xxxu_write32(priv, addr: regs[0], val: path_on); |
3095 | } |
3096 | |
3097 | for (i = 1 ; i < RTL8XXXU_ADDA_REGS ; i++) |
3098 | rtl8xxxu_write32(priv, addr: regs[i], val: path_on); |
3099 | } |
3100 | |
3101 | void rtl8xxxu_mac_calibration(struct rtl8xxxu_priv *priv, |
3102 | const u32 *regs, u32 *backup) |
3103 | { |
3104 | int i = 0; |
3105 | |
3106 | rtl8xxxu_write8(priv, addr: regs[i], val: 0x3f); |
3107 | |
3108 | for (i = 1 ; i < (RTL8XXXU_MAC_REGS - 1); i++) |
3109 | rtl8xxxu_write8(priv, addr: regs[i], val: (u8)(backup[i] & ~BIT(3))); |
3110 | |
3111 | rtl8xxxu_write8(priv, addr: regs[i], val: (u8)(backup[i] & ~BIT(5))); |
3112 | } |
3113 | |
3114 | static int rtl8xxxu_iqk_path_a(struct rtl8xxxu_priv *priv) |
3115 | { |
3116 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4, val32; |
3117 | int result = 0; |
3118 | |
3119 | /* path-A IQK setting */ |
3120 | rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, val: 0x10008c1f); |
3121 | rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, val: 0x10008c1f); |
3122 | rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, val: 0x82140102); |
3123 | |
3124 | val32 = (priv->rf_paths > 1) ? 0x28160202 : |
3125 | /*IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202: */ |
3126 | 0x28160502; |
3127 | rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, val: val32); |
3128 | |
3129 | /* path-B IQK setting */ |
3130 | if (priv->rf_paths > 1) { |
3131 | rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, val: 0x10008c22); |
3132 | rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, val: 0x10008c22); |
3133 | rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, val: 0x82140102); |
3134 | rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, val: 0x28160202); |
3135 | } |
3136 | |
3137 | /* LO calibration setting */ |
3138 | rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, val: 0x001028d1); |
3139 | |
3140 | /* One shot, path A LOK & IQK */ |
3141 | rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, val: 0xf9000000); |
3142 | rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, val: 0xf8000000); |
3143 | |
3144 | mdelay(1); |
3145 | |
3146 | /* Check failed */ |
3147 | reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); |
3148 | reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); |
3149 | reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); |
3150 | reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); |
3151 | |
3152 | if (!(reg_eac & BIT(28)) && |
3153 | ((reg_e94 & 0x03ff0000) != 0x01420000) && |
3154 | ((reg_e9c & 0x03ff0000) != 0x00420000)) |
3155 | result |= 0x01; |
3156 | else /* If TX not OK, ignore RX */ |
3157 | goto out; |
3158 | |
3159 | /* If TX is OK, check whether RX is OK */ |
3160 | if (!(reg_eac & BIT(27)) && |
3161 | ((reg_ea4 & 0x03ff0000) != 0x01320000) && |
3162 | ((reg_eac & 0x03ff0000) != 0x00360000)) |
3163 | result |= 0x02; |
3164 | else |
3165 | dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n" , |
3166 | __func__); |
3167 | out: |
3168 | return result; |
3169 | } |
3170 | |
3171 | static int rtl8xxxu_iqk_path_b(struct rtl8xxxu_priv *priv) |
3172 | { |
3173 | u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; |
3174 | int result = 0; |
3175 | |
3176 | /* One shot, path B LOK & IQK */ |
3177 | rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, val: 0x00000002); |
3178 | rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, val: 0x00000000); |
3179 | |
3180 | mdelay(1); |
3181 | |
3182 | /* Check failed */ |
3183 | reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); |
3184 | reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); |
3185 | reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); |
3186 | reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); |
3187 | reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); |
3188 | |
3189 | if (!(reg_eac & BIT(31)) && |
3190 | ((reg_eb4 & 0x03ff0000) != 0x01420000) && |
3191 | ((reg_ebc & 0x03ff0000) != 0x00420000)) |
3192 | result |= 0x01; |
3193 | else |
3194 | goto out; |
3195 | |
3196 | if (!(reg_eac & BIT(30)) && |
3197 | (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) && |
3198 | (((reg_ecc & 0x03ff0000) >> 16) != 0x36)) |
3199 | result |= 0x02; |
3200 | else |
3201 | dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n" , |
3202 | __func__); |
3203 | out: |
3204 | return result; |
3205 | } |
3206 | |
3207 | static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, |
3208 | int result[][8], int t) |
3209 | { |
3210 | struct device *dev = &priv->udev->dev; |
3211 | u32 i, val32; |
3212 | int path_a_ok, path_b_ok; |
3213 | int retry = 2; |
3214 | static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { |
3215 | REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, |
3216 | REG_RX_WAIT_CCA, REG_TX_CCK_RFON, |
3217 | REG_TX_CCK_BBON, REG_TX_OFDM_RFON, |
3218 | REG_TX_OFDM_BBON, REG_TX_TO_RX, |
3219 | REG_TX_TO_TX, REG_RX_CCK, |
3220 | REG_RX_OFDM, REG_RX_WAIT_RIFS, |
3221 | REG_RX_TO_RX, REG_STANDBY, |
3222 | REG_SLEEP, REG_PMPD_ANAEN |
3223 | }; |
3224 | static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { |
3225 | REG_TXPAUSE, REG_BEACON_CTRL, |
3226 | REG_BEACON_CTRL_1, REG_GPIO_MUXCFG |
3227 | }; |
3228 | static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { |
3229 | REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, |
3230 | REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, |
3231 | REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, |
3232 | REG_FPGA0_XB_RF_INT_OE, REG_FPGA0_RF_MODE |
3233 | }; |
3234 | |
3235 | /* |
3236 | * Note: IQ calibration must be performed after loading |
3237 | * PHY_REG.txt , and radio_a, radio_b.txt |
3238 | */ |
3239 | |
3240 | if (t == 0) { |
3241 | /* Save ADDA parameters, turn Path A ADDA on */ |
3242 | rtl8xxxu_save_regs(priv, regs: adda_regs, backup: priv->adda_backup, |
3243 | RTL8XXXU_ADDA_REGS); |
3244 | rtl8xxxu_save_mac_regs(priv, reg: iqk_mac_regs, backup: priv->mac_backup); |
3245 | rtl8xxxu_save_regs(priv, regs: iqk_bb_regs, |
3246 | backup: priv->bb_backup, RTL8XXXU_BB_REGS); |
3247 | } |
3248 | |
3249 | rtl8xxxu_path_adda_on(priv, regs: adda_regs, path_a_on: true); |
3250 | |
3251 | if (t == 0) { |
3252 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1); |
3253 | if (val32 & FPGA0_HSSI_PARM1_PI) |
3254 | priv->pi_enabled = 1; |
3255 | } |
3256 | |
3257 | if (!priv->pi_enabled) { |
3258 | /* Switch BB to PI mode to do IQ Calibration. */ |
3259 | rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val: 0x01000100); |
3260 | rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val: 0x01000100); |
3261 | } |
3262 | |
3263 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
3264 | val32 &= ~FPGA_RF_MODE_CCK; |
3265 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
3266 | |
3267 | rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val: 0x03a05600); |
3268 | rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, val: 0x000800e4); |
3269 | rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, val: 0x22204000); |
3270 | |
3271 | if (!priv->no_pape) { |
3272 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); |
3273 | val32 |= (FPGA0_RF_PAPE | |
3274 | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); |
3275 | rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val: val32); |
3276 | } |
3277 | |
3278 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); |
3279 | val32 &= ~BIT(10); |
3280 | rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val: val32); |
3281 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE); |
3282 | val32 &= ~BIT(10); |
3283 | rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val: val32); |
3284 | |
3285 | if (priv->tx_paths > 1) { |
3286 | rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, val: 0x00010000); |
3287 | rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, val: 0x00010000); |
3288 | } |
3289 | |
3290 | /* MAC settings */ |
3291 | rtl8xxxu_mac_calibration(priv, regs: iqk_mac_regs, backup: priv->mac_backup); |
3292 | |
3293 | /* Page B init */ |
3294 | rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, val: 0x00080000); |
3295 | |
3296 | if (priv->tx_paths > 1) |
3297 | rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, val: 0x00080000); |
3298 | |
3299 | /* IQ calibration setting */ |
3300 | rtl8xxxu_write32(priv, REG_FPGA0_IQK, val: 0x80800000); |
3301 | rtl8xxxu_write32(priv, REG_TX_IQK, val: 0x01007c00); |
3302 | rtl8xxxu_write32(priv, REG_RX_IQK, val: 0x01004800); |
3303 | |
3304 | for (i = 0; i < retry; i++) { |
3305 | path_a_ok = rtl8xxxu_iqk_path_a(priv); |
3306 | if (path_a_ok == 0x03) { |
3307 | val32 = rtl8xxxu_read32(priv, |
3308 | REG_TX_POWER_BEFORE_IQK_A); |
3309 | result[t][0] = (val32 >> 16) & 0x3ff; |
3310 | val32 = rtl8xxxu_read32(priv, |
3311 | REG_TX_POWER_AFTER_IQK_A); |
3312 | result[t][1] = (val32 >> 16) & 0x3ff; |
3313 | val32 = rtl8xxxu_read32(priv, |
3314 | REG_RX_POWER_BEFORE_IQK_A_2); |
3315 | result[t][2] = (val32 >> 16) & 0x3ff; |
3316 | val32 = rtl8xxxu_read32(priv, |
3317 | REG_RX_POWER_AFTER_IQK_A_2); |
3318 | result[t][3] = (val32 >> 16) & 0x3ff; |
3319 | break; |
3320 | } else if (i == (retry - 1) && path_a_ok == 0x01) { |
3321 | /* TX IQK OK */ |
3322 | dev_dbg(dev, "%s: Path A IQK Only Tx Success!!\n" , |
3323 | __func__); |
3324 | |
3325 | val32 = rtl8xxxu_read32(priv, |
3326 | REG_TX_POWER_BEFORE_IQK_A); |
3327 | result[t][0] = (val32 >> 16) & 0x3ff; |
3328 | val32 = rtl8xxxu_read32(priv, |
3329 | REG_TX_POWER_AFTER_IQK_A); |
3330 | result[t][1] = (val32 >> 16) & 0x3ff; |
3331 | } |
3332 | } |
3333 | |
3334 | if (!path_a_ok) |
3335 | dev_dbg(dev, "%s: Path A IQK failed!\n" , __func__); |
3336 | |
3337 | if (priv->tx_paths > 1) { |
3338 | /* |
3339 | * Path A into standby |
3340 | */ |
3341 | rtl8xxxu_write32(priv, REG_FPGA0_IQK, val: 0x0); |
3342 | rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, val: 0x00010000); |
3343 | rtl8xxxu_write32(priv, REG_FPGA0_IQK, val: 0x80800000); |
3344 | |
3345 | /* Turn Path B ADDA on */ |
3346 | rtl8xxxu_path_adda_on(priv, regs: adda_regs, path_a_on: false); |
3347 | |
3348 | for (i = 0; i < retry; i++) { |
3349 | path_b_ok = rtl8xxxu_iqk_path_b(priv); |
3350 | if (path_b_ok == 0x03) { |
3351 | val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); |
3352 | result[t][4] = (val32 >> 16) & 0x3ff; |
3353 | val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); |
3354 | result[t][5] = (val32 >> 16) & 0x3ff; |
3355 | val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); |
3356 | result[t][6] = (val32 >> 16) & 0x3ff; |
3357 | val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); |
3358 | result[t][7] = (val32 >> 16) & 0x3ff; |
3359 | break; |
3360 | } else if (i == (retry - 1) && path_b_ok == 0x01) { |
3361 | /* TX IQK OK */ |
3362 | val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); |
3363 | result[t][4] = (val32 >> 16) & 0x3ff; |
3364 | val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); |
3365 | result[t][5] = (val32 >> 16) & 0x3ff; |
3366 | } |
3367 | } |
3368 | |
3369 | if (!path_b_ok) |
3370 | dev_dbg(dev, "%s: Path B IQK failed!\n" , __func__); |
3371 | } |
3372 | |
3373 | /* Back to BB mode, load original value */ |
3374 | rtl8xxxu_write32(priv, REG_FPGA0_IQK, val: 0); |
3375 | |
3376 | if (t) { |
3377 | if (!priv->pi_enabled) { |
3378 | /* |
3379 | * Switch back BB to SI mode after finishing |
3380 | * IQ Calibration |
3381 | */ |
3382 | val32 = 0x01000000; |
3383 | rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val: val32); |
3384 | rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val: val32); |
3385 | } |
3386 | |
3387 | /* Reload ADDA power saving parameters */ |
3388 | rtl8xxxu_restore_regs(priv, regs: adda_regs, backup: priv->adda_backup, |
3389 | RTL8XXXU_ADDA_REGS); |
3390 | |
3391 | /* Reload MAC parameters */ |
3392 | rtl8xxxu_restore_mac_regs(priv, reg: iqk_mac_regs, backup: priv->mac_backup); |
3393 | |
3394 | /* Reload BB parameters */ |
3395 | rtl8xxxu_restore_regs(priv, regs: iqk_bb_regs, |
3396 | backup: priv->bb_backup, RTL8XXXU_BB_REGS); |
3397 | |
3398 | /* Restore RX initial gain */ |
3399 | rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, val: 0x00032ed3); |
3400 | |
3401 | if (priv->tx_paths > 1) { |
3402 | rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, |
3403 | val: 0x00032ed3); |
3404 | } |
3405 | |
3406 | /* Load 0xe30 IQC default value */ |
3407 | rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, val: 0x01008c00); |
3408 | rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, val: 0x01008c00); |
3409 | } |
3410 | } |
3411 | |
3412 | void rtl8xxxu_gen2_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start) |
3413 | { |
3414 | struct h2c_cmd h2c; |
3415 | |
3416 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
3417 | h2c.bt_wlan_calibration.cmd = H2C_8723B_BT_WLAN_CALIBRATION; |
3418 | h2c.bt_wlan_calibration.data = start; |
3419 | |
3420 | rtl8xxxu_gen2_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.bt_wlan_calibration)); |
3421 | } |
3422 | |
3423 | void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv) |
3424 | { |
3425 | struct device *dev = &priv->udev->dev; |
3426 | int result[4][8]; /* last is final result */ |
3427 | int i, candidate; |
3428 | bool path_a_ok, path_b_ok; |
3429 | u32 reg_e94, reg_e9c, reg_ea4, reg_eac; |
3430 | u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; |
3431 | s32 reg_tmp = 0; |
3432 | bool simu; |
3433 | |
3434 | memset(result, 0, sizeof(result)); |
3435 | candidate = -1; |
3436 | |
3437 | path_a_ok = false; |
3438 | path_b_ok = false; |
3439 | |
3440 | rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
3441 | |
3442 | for (i = 0; i < 3; i++) { |
3443 | rtl8xxxu_phy_iqcalibrate(priv, result, t: i); |
3444 | |
3445 | if (i == 1) { |
3446 | simu = rtl8xxxu_simularity_compare(priv, result, c1: 0, c2: 1); |
3447 | if (simu) { |
3448 | candidate = 0; |
3449 | break; |
3450 | } |
3451 | } |
3452 | |
3453 | if (i == 2) { |
3454 | simu = rtl8xxxu_simularity_compare(priv, result, c1: 0, c2: 2); |
3455 | if (simu) { |
3456 | candidate = 0; |
3457 | break; |
3458 | } |
3459 | |
3460 | simu = rtl8xxxu_simularity_compare(priv, result, c1: 1, c2: 2); |
3461 | if (simu) { |
3462 | candidate = 1; |
3463 | } else { |
3464 | for (i = 0; i < 8; i++) |
3465 | reg_tmp += result[3][i]; |
3466 | |
3467 | if (reg_tmp) |
3468 | candidate = 3; |
3469 | else |
3470 | candidate = -1; |
3471 | } |
3472 | } |
3473 | } |
3474 | |
3475 | for (i = 0; i < 4; i++) { |
3476 | reg_e94 = result[i][0]; |
3477 | reg_e9c = result[i][1]; |
3478 | reg_ea4 = result[i][2]; |
3479 | reg_eac = result[i][3]; |
3480 | reg_eb4 = result[i][4]; |
3481 | reg_ebc = result[i][5]; |
3482 | reg_ec4 = result[i][6]; |
3483 | reg_ecc = result[i][7]; |
3484 | } |
3485 | |
3486 | if (candidate >= 0) { |
3487 | reg_e94 = result[candidate][0]; |
3488 | priv->rege94 = reg_e94; |
3489 | reg_e9c = result[candidate][1]; |
3490 | priv->rege9c = reg_e9c; |
3491 | reg_ea4 = result[candidate][2]; |
3492 | reg_eac = result[candidate][3]; |
3493 | reg_eb4 = result[candidate][4]; |
3494 | priv->regeb4 = reg_eb4; |
3495 | reg_ebc = result[candidate][5]; |
3496 | priv->regebc = reg_ebc; |
3497 | reg_ec4 = result[candidate][6]; |
3498 | reg_ecc = result[candidate][7]; |
3499 | dev_dbg(dev, "%s: candidate is %x\n" , __func__, candidate); |
3500 | dev_dbg(dev, |
3501 | "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%x\n" , |
3502 | __func__, reg_e94, reg_e9c, |
3503 | reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc); |
3504 | path_a_ok = true; |
3505 | path_b_ok = true; |
3506 | } else { |
3507 | reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100; |
3508 | reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0; |
3509 | } |
3510 | |
3511 | if (reg_e94 && candidate >= 0) |
3512 | rtl8xxxu_fill_iqk_matrix_a(priv, iqk_ok: path_a_ok, result, |
3513 | candidate, tx_only: (reg_ea4 == 0)); |
3514 | |
3515 | if (priv->tx_paths > 1 && reg_eb4) |
3516 | rtl8xxxu_fill_iqk_matrix_b(priv, iqk_ok: path_b_ok, result, |
3517 | candidate, tx_only: (reg_ec4 == 0)); |
3518 | |
3519 | rtl8xxxu_save_regs(priv, regs: rtl8xxxu_iqk_phy_iq_bb_reg, |
3520 | backup: priv->bb_recovery_backup, RTL8XXXU_BB_REGS); |
3521 | } |
3522 | |
3523 | void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv) |
3524 | { |
3525 | u32 val32; |
3526 | u32 rf_amode, rf_bmode = 0, lstf; |
3527 | |
3528 | /* Check continuous TX and Packet TX */ |
3529 | lstf = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); |
3530 | |
3531 | if (lstf & OFDM_LSTF_MASK) { |
3532 | /* Disable all continuous TX */ |
3533 | val32 = lstf & ~OFDM_LSTF_MASK; |
3534 | rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val: val32); |
3535 | |
3536 | /* Read original RF mode Path A */ |
3537 | rf_amode = rtl8xxxu_read_rfreg(priv, path: RF_A, RF6052_REG_AC); |
3538 | |
3539 | /* Set RF mode to standby Path A */ |
3540 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_AC, |
3541 | data: (rf_amode & 0x8ffff) | 0x10000); |
3542 | |
3543 | /* Path-B */ |
3544 | if (priv->tx_paths > 1) { |
3545 | rf_bmode = rtl8xxxu_read_rfreg(priv, path: RF_B, |
3546 | RF6052_REG_AC); |
3547 | |
3548 | rtl8xxxu_write_rfreg(priv, path: RF_B, RF6052_REG_AC, |
3549 | data: (rf_bmode & 0x8ffff) | 0x10000); |
3550 | } |
3551 | } else { |
3552 | /* Deal with Packet TX case */ |
3553 | /* block all queues */ |
3554 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0xff); |
3555 | } |
3556 | |
3557 | /* Start LC calibration */ |
3558 | if (priv->fops->has_s0s1) |
3559 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_S0S1, data: 0xdfbe0); |
3560 | val32 = rtl8xxxu_read_rfreg(priv, path: RF_A, RF6052_REG_MODE_AG); |
3561 | val32 |= 0x08000; |
3562 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_MODE_AG, data: val32); |
3563 | |
3564 | msleep(msecs: 100); |
3565 | |
3566 | if (priv->fops->has_s0s1) |
3567 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_S0S1, data: 0xdffe0); |
3568 | |
3569 | /* Restore original parameters */ |
3570 | if (lstf & OFDM_LSTF_MASK) { |
3571 | /* Path-A */ |
3572 | rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val: lstf); |
3573 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_AC, data: rf_amode); |
3574 | |
3575 | /* Path-B */ |
3576 | if (priv->tx_paths > 1) |
3577 | rtl8xxxu_write_rfreg(priv, path: RF_B, RF6052_REG_AC, |
3578 | data: rf_bmode); |
3579 | } else /* Deal with Packet TX case */ |
3580 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0x00); |
3581 | } |
3582 | |
3583 | static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv, int port_num) |
3584 | { |
3585 | int i; |
3586 | u16 reg; |
3587 | |
3588 | switch (port_num) { |
3589 | case 0: |
3590 | reg = REG_MACID; |
3591 | break; |
3592 | case 1: |
3593 | reg = REG_MACID1; |
3594 | break; |
3595 | default: |
3596 | WARN_ONCE(1, "%s: invalid port_num\n" , __func__); |
3597 | return -EINVAL; |
3598 | } |
3599 | |
3600 | for (i = 0; i < ETH_ALEN; i++) |
3601 | rtl8xxxu_write8(priv, addr: reg + i, val: priv->vifs[port_num]->addr[i]); |
3602 | |
3603 | return 0; |
3604 | } |
3605 | |
3606 | static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid, int port_num) |
3607 | { |
3608 | int i; |
3609 | u16 reg; |
3610 | |
3611 | dev_dbg(&priv->udev->dev, "%s: (%pM)\n" , __func__, bssid); |
3612 | |
3613 | switch (port_num) { |
3614 | case 0: |
3615 | reg = REG_BSSID; |
3616 | break; |
3617 | case 1: |
3618 | reg = REG_BSSID1; |
3619 | break; |
3620 | default: |
3621 | WARN_ONCE(1, "%s: invalid port_num\n" , __func__); |
3622 | return -EINVAL; |
3623 | } |
3624 | |
3625 | for (i = 0; i < ETH_ALEN; i++) |
3626 | rtl8xxxu_write8(priv, addr: reg + i, val: bssid[i]); |
3627 | |
3628 | return 0; |
3629 | } |
3630 | |
3631 | static void |
3632 | rtl8xxxu_set_ampdu_factor(struct rtl8xxxu_priv *priv, u8 ampdu_factor) |
3633 | { |
3634 | u8 vals[4] = { 0x41, 0xa8, 0x72, 0xb9 }; |
3635 | u8 max_agg = 0xf; |
3636 | int i; |
3637 | |
3638 | ampdu_factor = 1 << (ampdu_factor + 2); |
3639 | if (ampdu_factor > max_agg) |
3640 | ampdu_factor = max_agg; |
3641 | |
3642 | for (i = 0; i < 4; i++) { |
3643 | if ((vals[i] & 0xf0) > (ampdu_factor << 4)) |
3644 | vals[i] = (vals[i] & 0x0f) | (ampdu_factor << 4); |
3645 | |
3646 | if ((vals[i] & 0x0f) > ampdu_factor) |
3647 | vals[i] = (vals[i] & 0xf0) | ampdu_factor; |
3648 | |
3649 | rtl8xxxu_write8(priv, REG_AGGLEN_LMT + i, val: vals[i]); |
3650 | } |
3651 | } |
3652 | |
3653 | static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) |
3654 | { |
3655 | u8 val8; |
3656 | |
3657 | val8 = rtl8xxxu_read8(priv, REG_AMPDU_MIN_SPACE); |
3658 | val8 &= 0xf8; |
3659 | val8 |= density; |
3660 | rtl8xxxu_write8(priv, REG_AMPDU_MIN_SPACE, val: val8); |
3661 | } |
3662 | |
3663 | static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) |
3664 | { |
3665 | u8 val8; |
3666 | int count, ret = 0; |
3667 | |
3668 | /* Start of rtl8723AU_card_enable_flow */ |
3669 | /* Act to Cardemu sequence*/ |
3670 | /* Turn off RF */ |
3671 | rtl8xxxu_write8(priv, REG_RF_CTRL, val: 0); |
3672 | |
3673 | /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */ |
3674 | val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); |
3675 | val8 &= ~LEDCFG2_DPDT_SELECT; |
3676 | rtl8xxxu_write8(priv, REG_LEDCFG2, val: val8); |
3677 | |
3678 | /* 0x0005[1] = 1 turn off MAC by HW state machine*/ |
3679 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3680 | val8 |= BIT(1); |
3681 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val: val8); |
3682 | |
3683 | for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { |
3684 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3685 | if ((val8 & BIT(1)) == 0) |
3686 | break; |
3687 | udelay(10); |
3688 | } |
3689 | |
3690 | if (!count) { |
3691 | dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n" , |
3692 | __func__); |
3693 | ret = -EBUSY; |
3694 | goto exit; |
3695 | } |
3696 | |
3697 | /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */ |
3698 | val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); |
3699 | val8 |= SYS_ISO_ANALOG_IPS; |
3700 | rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val: val8); |
3701 | |
3702 | /* 0x0020[0] = 0 disable LDOA12 MACRO block*/ |
3703 | val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); |
3704 | val8 &= ~LDOA15_ENABLE; |
3705 | rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val: val8); |
3706 | |
3707 | exit: |
3708 | return ret; |
3709 | } |
3710 | |
3711 | int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) |
3712 | { |
3713 | u8 val8; |
3714 | u8 val32; |
3715 | int count, ret = 0; |
3716 | |
3717 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0xff); |
3718 | |
3719 | /* |
3720 | * Poll - wait for RX packet to complete |
3721 | */ |
3722 | for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { |
3723 | val32 = rtl8xxxu_read32(priv, addr: 0x5f8); |
3724 | if (!val32) |
3725 | break; |
3726 | udelay(10); |
3727 | } |
3728 | |
3729 | if (!count) { |
3730 | dev_warn(&priv->udev->dev, |
3731 | "%s: RX poll timed out (0x05f8)\n" , __func__); |
3732 | ret = -EBUSY; |
3733 | goto exit; |
3734 | } |
3735 | |
3736 | /* Disable CCK and OFDM, clock gated */ |
3737 | val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); |
3738 | val8 &= ~SYS_FUNC_BBRSTB; |
3739 | rtl8xxxu_write8(priv, REG_SYS_FUNC, val: val8); |
3740 | |
3741 | udelay(2); |
3742 | |
3743 | /* Reset baseband */ |
3744 | val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); |
3745 | val8 &= ~SYS_FUNC_BB_GLB_RSTN; |
3746 | rtl8xxxu_write8(priv, REG_SYS_FUNC, val: val8); |
3747 | |
3748 | /* Reset MAC TRX */ |
3749 | val8 = rtl8xxxu_read8(priv, REG_CR); |
3750 | val8 = CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE; |
3751 | rtl8xxxu_write8(priv, REG_CR, val: val8); |
3752 | |
3753 | /* Reset MAC TRX */ |
3754 | val8 = rtl8xxxu_read8(priv, REG_CR + 1); |
3755 | val8 &= ~BIT(1); /* CR_SECURITY_ENABLE */ |
3756 | rtl8xxxu_write8(priv, REG_CR + 1, val: val8); |
3757 | |
3758 | /* Respond TX OK to scheduler */ |
3759 | val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST); |
3760 | val8 |= DUAL_TSF_TX_OK; |
3761 | rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val: val8); |
3762 | |
3763 | exit: |
3764 | return ret; |
3765 | } |
3766 | |
3767 | void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv) |
3768 | { |
3769 | u8 val8; |
3770 | |
3771 | /* Clear suspend enable and power down enable*/ |
3772 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3773 | val8 &= ~(BIT(3) | BIT(7)); |
3774 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val: val8); |
3775 | |
3776 | /* 0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ |
3777 | val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); |
3778 | val8 &= ~BIT(0); |
3779 | rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val: val8); |
3780 | |
3781 | /* 0x04[12:11] = 11 enable WL suspend*/ |
3782 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3783 | val8 &= ~(BIT(3) | BIT(4)); |
3784 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val: val8); |
3785 | } |
3786 | |
3787 | static int rtl8xxxu_emu_to_disabled(struct rtl8xxxu_priv *priv) |
3788 | { |
3789 | u8 val8; |
3790 | |
3791 | /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */ |
3792 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, val: 0x20); |
3793 | |
3794 | /* 0x04[12:11] = 01 enable WL suspend */ |
3795 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3796 | val8 &= ~BIT(4); |
3797 | val8 |= BIT(3); |
3798 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val: val8); |
3799 | |
3800 | val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); |
3801 | val8 |= BIT(7); |
3802 | rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val: val8); |
3803 | |
3804 | /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ |
3805 | val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); |
3806 | val8 |= BIT(0); |
3807 | rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val: val8); |
3808 | |
3809 | return 0; |
3810 | } |
3811 | |
3812 | int rtl8xxxu_flush_fifo(struct rtl8xxxu_priv *priv) |
3813 | { |
3814 | struct device *dev = &priv->udev->dev; |
3815 | u32 val32; |
3816 | int retry, retval; |
3817 | |
3818 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0xff); |
3819 | |
3820 | val32 = rtl8xxxu_read32(priv, REG_RXPKT_NUM); |
3821 | val32 |= RXPKT_NUM_RW_RELEASE_EN; |
3822 | rtl8xxxu_write32(priv, REG_RXPKT_NUM, val: val32); |
3823 | |
3824 | retry = 100; |
3825 | retval = -EBUSY; |
3826 | |
3827 | do { |
3828 | val32 = rtl8xxxu_read32(priv, REG_RXPKT_NUM); |
3829 | if (val32 & RXPKT_NUM_RXDMA_IDLE) { |
3830 | retval = 0; |
3831 | break; |
3832 | } |
3833 | } while (retry--); |
3834 | |
3835 | rtl8xxxu_write16(priv, REG_RQPN_NPQ, val: 0); |
3836 | rtl8xxxu_write32(priv, REG_RQPN, val: 0x80000000); |
3837 | mdelay(2); |
3838 | |
3839 | if (!retry) |
3840 | dev_warn(dev, "Failed to flush FIFO\n" ); |
3841 | |
3842 | return retval; |
3843 | } |
3844 | |
3845 | void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv) |
3846 | { |
3847 | /* Fix USB interface interference issue */ |
3848 | rtl8xxxu_write8(priv, addr: 0xfe40, val: 0xe0); |
3849 | rtl8xxxu_write8(priv, addr: 0xfe41, val: 0x8d); |
3850 | rtl8xxxu_write8(priv, addr: 0xfe42, val: 0x80); |
3851 | /* |
3852 | * This sets TXDMA_OFFSET_DROP_DATA_EN (bit 9) as well as bits |
3853 | * 8 and 5, for which I have found no documentation. |
3854 | */ |
3855 | rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val: 0xfd0320); |
3856 | |
3857 | /* |
3858 | * Solve too many protocol error on USB bus. |
3859 | * Can't do this for 8188/8192 UMC A cut parts |
3860 | */ |
3861 | if (!(!priv->chip_cut && priv->vendor_umc)) { |
3862 | rtl8xxxu_write8(priv, addr: 0xfe40, val: 0xe6); |
3863 | rtl8xxxu_write8(priv, addr: 0xfe41, val: 0x94); |
3864 | rtl8xxxu_write8(priv, addr: 0xfe42, val: 0x80); |
3865 | |
3866 | rtl8xxxu_write8(priv, addr: 0xfe40, val: 0xe0); |
3867 | rtl8xxxu_write8(priv, addr: 0xfe41, val: 0x19); |
3868 | rtl8xxxu_write8(priv, addr: 0xfe42, val: 0x80); |
3869 | |
3870 | rtl8xxxu_write8(priv, addr: 0xfe40, val: 0xe5); |
3871 | rtl8xxxu_write8(priv, addr: 0xfe41, val: 0x91); |
3872 | rtl8xxxu_write8(priv, addr: 0xfe42, val: 0x80); |
3873 | |
3874 | rtl8xxxu_write8(priv, addr: 0xfe40, val: 0xe2); |
3875 | rtl8xxxu_write8(priv, addr: 0xfe41, val: 0x81); |
3876 | rtl8xxxu_write8(priv, addr: 0xfe42, val: 0x80); |
3877 | } |
3878 | } |
3879 | |
3880 | void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv) |
3881 | { |
3882 | u32 val32; |
3883 | |
3884 | val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); |
3885 | val32 |= TXDMA_OFFSET_DROP_DATA_EN; |
3886 | rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val: val32); |
3887 | } |
3888 | |
3889 | void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) |
3890 | { |
3891 | u8 val8; |
3892 | u16 val16; |
3893 | u32 val32; |
3894 | |
3895 | /* |
3896 | * Workaround for 8188RU LNA power leakage problem. |
3897 | */ |
3898 | if (priv->rtl_chip == RTL8188R) { |
3899 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); |
3900 | val32 |= BIT(1); |
3901 | rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val: val32); |
3902 | } |
3903 | |
3904 | rtl8xxxu_flush_fifo(priv); |
3905 | |
3906 | rtl8xxxu_active_to_lps(priv); |
3907 | |
3908 | /* Turn off RF */ |
3909 | rtl8xxxu_write8(priv, REG_RF_CTRL, val: 0x00); |
3910 | |
3911 | /* Reset Firmware if running in RAM */ |
3912 | if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) |
3913 | rtl8xxxu_firmware_self_reset(priv); |
3914 | |
3915 | /* Reset MCU */ |
3916 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
3917 | val16 &= ~SYS_FUNC_CPU_ENABLE; |
3918 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val: val16); |
3919 | |
3920 | /* Reset MCU ready status */ |
3921 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, val: 0x00); |
3922 | |
3923 | rtl8xxxu_active_to_emu(priv); |
3924 | rtl8xxxu_emu_to_disabled(priv); |
3925 | |
3926 | /* Reset MCU IO Wrapper */ |
3927 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); |
3928 | val8 &= ~BIT(0); |
3929 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val: val8); |
3930 | |
3931 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); |
3932 | val8 |= BIT(0); |
3933 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val: val8); |
3934 | |
3935 | /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */ |
3936 | rtl8xxxu_write8(priv, REG_RSV_CTRL, val: 0x0e); |
3937 | } |
3938 | |
3939 | void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, |
3940 | u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5) |
3941 | { |
3942 | struct h2c_cmd h2c; |
3943 | |
3944 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
3945 | h2c.b_type_dma.cmd = H2C_8723B_B_TYPE_TDMA; |
3946 | h2c.b_type_dma.data1 = arg1; |
3947 | h2c.b_type_dma.data2 = arg2; |
3948 | h2c.b_type_dma.data3 = arg3; |
3949 | h2c.b_type_dma.data4 = arg4; |
3950 | h2c.b_type_dma.data5 = arg5; |
3951 | rtl8xxxu_gen2_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.b_type_dma)); |
3952 | } |
3953 | |
3954 | void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv) |
3955 | { |
3956 | u32 val32; |
3957 | |
3958 | val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA); |
3959 | val32 &= ~(BIT(22) | BIT(23)); |
3960 | rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val: val32); |
3961 | } |
3962 | |
3963 | static void rtl8xxxu_init_queue_reserved_page(struct rtl8xxxu_priv *priv) |
3964 | { |
3965 | struct rtl8xxxu_fileops *fops = priv->fops; |
3966 | u32 hq, lq, nq, eq, pubq; |
3967 | u32 val32; |
3968 | |
3969 | hq = 0; |
3970 | lq = 0; |
3971 | nq = 0; |
3972 | eq = 0; |
3973 | pubq = 0; |
3974 | |
3975 | if (priv->ep_tx_high_queue) |
3976 | hq = fops->page_num_hi; |
3977 | if (priv->ep_tx_low_queue) |
3978 | lq = fops->page_num_lo; |
3979 | if (priv->ep_tx_normal_queue) |
3980 | nq = fops->page_num_norm; |
3981 | |
3982 | val32 = (nq << RQPN_NPQ_SHIFT) | (eq << RQPN_EPQ_SHIFT); |
3983 | rtl8xxxu_write32(priv, REG_RQPN_NPQ, val: val32); |
3984 | |
3985 | pubq = fops->total_page_num - hq - lq - nq - 1; |
3986 | |
3987 | val32 = RQPN_LOAD; |
3988 | val32 |= (hq << RQPN_HI_PQ_SHIFT); |
3989 | val32 |= (lq << RQPN_LO_PQ_SHIFT); |
3990 | val32 |= (pubq << RQPN_PUB_PQ_SHIFT); |
3991 | |
3992 | rtl8xxxu_write32(priv, REG_RQPN, val: val32); |
3993 | } |
3994 | |
3995 | void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv) |
3996 | { |
3997 | u8 val8; |
3998 | |
3999 | /* |
4000 | * For USB high speed set 512B packets |
4001 | */ |
4002 | val8 = rtl8xxxu_read8(priv, REG_RXDMA_PRO_8723B); |
4003 | u8p_replace_bits(p: &val8, val: 1, RXDMA_PRO_DMA_BURST_SIZE); |
4004 | u8p_replace_bits(p: &val8, val: 3, RXDMA_PRO_DMA_BURST_CNT); |
4005 | val8 |= RXDMA_PRO_DMA_MODE; |
4006 | rtl8xxxu_write8(priv, REG_RXDMA_PRO_8723B, val: val8); |
4007 | |
4008 | /* |
4009 | * Enable single packet AMPDU |
4010 | */ |
4011 | val8 = rtl8xxxu_read8(priv, REG_HT_SINGLE_AMPDU_8723B); |
4012 | val8 |= HT_SINGLE_AMPDU_ENABLE; |
4013 | rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val: val8); |
4014 | |
4015 | rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, val: priv->fops->max_aggr_num); |
4016 | rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, |
4017 | val: priv->fops->ampdu_max_time); |
4018 | rtl8xxxu_write32(priv, REG_AGGLEN_LMT, val: 0xffffffff); |
4019 | rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, val: 0x18); |
4020 | rtl8xxxu_write8(priv, REG_PIFS, val: 0x00); |
4021 | if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B || |
4022 | priv->rtl_chip == RTL8192F) { |
4023 | rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY); |
4024 | rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, val: 0x03086666); |
4025 | } |
4026 | rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, val: priv->fops->ustime_tsf_edca); |
4027 | rtl8xxxu_write8(priv, REG_USTIME_EDCA, val: priv->fops->ustime_tsf_edca); |
4028 | |
4029 | /* to prevent mac is reseted by bus. */ |
4030 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL); |
4031 | val8 |= RSV_CTRL_WLOCK_1C | RSV_CTRL_DIS_PRST; |
4032 | rtl8xxxu_write8(priv, REG_RSV_CTRL, val: val8); |
4033 | } |
4034 | |
4035 | static u8 rtl8xxxu_acquire_macid(struct rtl8xxxu_priv *priv) |
4036 | { |
4037 | u8 macid; |
4038 | |
4039 | macid = find_first_zero_bit(addr: priv->mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM); |
4040 | if (macid < RTL8XXXU_MAX_MAC_ID_NUM) |
4041 | set_bit(nr: macid, addr: priv->mac_id_map); |
4042 | |
4043 | return macid; |
4044 | } |
4045 | |
4046 | static void rtl8xxxu_release_macid(struct rtl8xxxu_priv *priv, u8 macid) |
4047 | { |
4048 | clear_bit(nr: macid, addr: priv->mac_id_map); |
4049 | } |
4050 | |
4051 | static inline u8 rtl8xxxu_get_macid(struct rtl8xxxu_priv *priv, |
4052 | struct ieee80211_sta *sta) |
4053 | { |
4054 | struct rtl8xxxu_sta_info *sta_info; |
4055 | |
4056 | if (!sta) |
4057 | return 0; |
4058 | |
4059 | sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
4060 | if (!sta_info) |
4061 | return 0; |
4062 | |
4063 | return sta_info->macid; |
4064 | } |
4065 | |
4066 | static int rtl8xxxu_init_device(struct ieee80211_hw *hw) |
4067 | { |
4068 | struct rtl8xxxu_priv *priv = hw->priv; |
4069 | struct device *dev = &priv->udev->dev; |
4070 | struct rtl8xxxu_fileops *fops = priv->fops; |
4071 | bool macpower; |
4072 | int ret; |
4073 | u8 val8; |
4074 | u16 val16; |
4075 | u32 val32; |
4076 | |
4077 | /* Check if MAC is already powered on */ |
4078 | val8 = rtl8xxxu_read8(priv, REG_CR); |
4079 | val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); |
4080 | |
4081 | /* |
4082 | * Fix 92DU-VC S3 hang with the reason is that secondary mac is not |
4083 | * initialized. First MAC returns 0xea, second MAC returns 0x00 |
4084 | */ |
4085 | if (val8 == 0xea || !(val16 & SYS_CLK_MAC_CLK_ENABLE)) |
4086 | macpower = false; |
4087 | else |
4088 | macpower = true; |
4089 | |
4090 | if (fops->needs_full_init) |
4091 | macpower = false; |
4092 | |
4093 | ret = fops->power_on(priv); |
4094 | if (ret < 0) { |
4095 | dev_warn(dev, "%s: Failed power on\n" , __func__); |
4096 | goto exit; |
4097 | } |
4098 | |
4099 | if (!macpower) |
4100 | rtl8xxxu_init_queue_reserved_page(priv); |
4101 | |
4102 | ret = rtl8xxxu_init_queue_priority(priv); |
4103 | dev_dbg(dev, "%s: init_queue_priority %i\n" , __func__, ret); |
4104 | if (ret) |
4105 | goto exit; |
4106 | |
4107 | /* |
4108 | * Set RX page boundary |
4109 | */ |
4110 | rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, val: fops->trxff_boundary); |
4111 | |
4112 | ret = rtl8xxxu_download_firmware(priv); |
4113 | dev_dbg(dev, "%s: download_firmware %i\n" , __func__, ret); |
4114 | if (ret) |
4115 | goto exit; |
4116 | ret = rtl8xxxu_start_firmware(priv); |
4117 | dev_dbg(dev, "%s: start_firmware %i\n" , __func__, ret); |
4118 | if (ret) |
4119 | goto exit; |
4120 | |
4121 | if (fops->phy_init_antenna_selection) |
4122 | fops->phy_init_antenna_selection(priv); |
4123 | |
4124 | ret = rtl8xxxu_init_mac(priv); |
4125 | |
4126 | dev_dbg(dev, "%s: init_mac %i\n" , __func__, ret); |
4127 | if (ret) |
4128 | goto exit; |
4129 | |
4130 | ret = rtl8xxxu_init_phy_bb(priv); |
4131 | dev_dbg(dev, "%s: init_phy_bb %i\n" , __func__, ret); |
4132 | if (ret) |
4133 | goto exit; |
4134 | |
4135 | ret = fops->init_phy_rf(priv); |
4136 | if (ret) |
4137 | goto exit; |
4138 | |
4139 | /* Mac APLL Setting */ |
4140 | if (priv->rtl_chip == RTL8192F) |
4141 | rtl8xxxu_write16_set(priv, REG_AFE_CTRL4, BIT(4) | BIT(15)); |
4142 | |
4143 | /* RFSW Control - clear bit 14 ?? */ |
4144 | if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E && |
4145 | priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B && |
4146 | priv->rtl_chip != RTL8192F) |
4147 | rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, val: 0x00000003); |
4148 | |
4149 | val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | |
4150 | FPGA0_RF_ANTSWB | |
4151 | ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB) << FPGA0_RF_BD_CTRL_SHIFT); |
4152 | if (!priv->no_pape) { |
4153 | val32 |= (FPGA0_RF_PAPE | |
4154 | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); |
4155 | } |
4156 | rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val: val32); |
4157 | |
4158 | /* 0x860[6:5]= 00 - why? - this sets antenna B */ |
4159 | if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E && |
4160 | priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) |
4161 | rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val: 0x66f60210); |
4162 | |
4163 | if (!macpower) { |
4164 | /* |
4165 | * Set TX buffer boundary |
4166 | */ |
4167 | val8 = fops->total_page_num + 1; |
4168 | |
4169 | rtl8xxxu_write8(priv, REG_TXPKTBUF_BCNQ_BDNY, val: val8); |
4170 | rtl8xxxu_write8(priv, REG_TXPKTBUF_MGQ_BDNY, val: val8); |
4171 | rtl8xxxu_write8(priv, REG_TXPKTBUF_WMAC_LBK_BF_HD, val: val8); |
4172 | rtl8xxxu_write8(priv, REG_TRXFF_BNDY, val: val8); |
4173 | rtl8xxxu_write8(priv, REG_TDECTRL + 1, val: val8); |
4174 | } |
4175 | |
4176 | /* |
4177 | * The vendor drivers set PBP for all devices, except 8192e. |
4178 | * There is no explanation for this in any of the sources. |
4179 | */ |
4180 | val8 = (fops->pbp_rx << PBP_PAGE_SIZE_RX_SHIFT) | |
4181 | (fops->pbp_tx << PBP_PAGE_SIZE_TX_SHIFT); |
4182 | if (priv->rtl_chip != RTL8192E) |
4183 | rtl8xxxu_write8(priv, REG_PBP, val: val8); |
4184 | |
4185 | dev_dbg(dev, "%s: macpower %i\n" , __func__, macpower); |
4186 | if (!macpower) { |
4187 | ret = fops->llt_init(priv); |
4188 | if (ret) { |
4189 | dev_warn(dev, "%s: LLT table init failed\n" , __func__); |
4190 | goto exit; |
4191 | } |
4192 | |
4193 | /* |
4194 | * Chip specific quirks |
4195 | */ |
4196 | fops->usb_quirks(priv); |
4197 | |
4198 | /* |
4199 | * Enable TX report and TX report timer for 8723bu/8188eu/... |
4200 | */ |
4201 | if (fops->has_tx_report) { |
4202 | /* |
4203 | * The RTL8188EU has two types of TX reports: |
4204 | * rpt_sel=1: |
4205 | * One report for one frame. We can use this for frames |
4206 | * with IEEE80211_TX_CTL_REQ_TX_STATUS. |
4207 | * rpt_sel=2: |
4208 | * One report for many frames transmitted over a period |
4209 | * of time. (This is what REG_TX_REPORT_TIME is for.) The |
4210 | * report includes the number of frames transmitted |
4211 | * successfully, and the number of unsuccessful |
4212 | * transmissions. We use this for software rate control. |
4213 | * |
4214 | * Bit 0 of REG_TX_REPORT_CTRL is required for both types. |
4215 | * Bit 1 (TX_REPORT_CTRL_TIMER_ENABLE) is required for |
4216 | * type 2. |
4217 | */ |
4218 | val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); |
4219 | if (priv->rtl_chip == RTL8188E) |
4220 | val8 |= BIT(0); |
4221 | val8 |= TX_REPORT_CTRL_TIMER_ENABLE; |
4222 | rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val: val8); |
4223 | /* Set MAX RPT MACID */ |
4224 | rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, val: 0x02); |
4225 | /* TX report Timer. Unit: 32us */ |
4226 | rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, val: 0xcdf0); |
4227 | |
4228 | /* tmp ps ? */ |
4229 | val8 = rtl8xxxu_read8(priv, addr: 0xa3); |
4230 | val8 &= 0xf8; |
4231 | rtl8xxxu_write8(priv, addr: 0xa3, val: val8); |
4232 | } |
4233 | |
4234 | if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) |
4235 | rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, val: 0); |
4236 | } |
4237 | |
4238 | /* |
4239 | * Unit in 8 bytes. |
4240 | * Get Rx PHY status in order to report RSSI and others. |
4241 | */ |
4242 | rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, val: 4); |
4243 | |
4244 | if (priv->rtl_chip == RTL8192E) { |
4245 | rtl8xxxu_write32(priv, REG_HIMR0, val: 0x00); |
4246 | rtl8xxxu_write32(priv, REG_HIMR1, val: 0x00); |
4247 | } else if (priv->rtl_chip == RTL8188F) { |
4248 | rtl8xxxu_write32(priv, REG_HISR0, val: 0xffffffff); |
4249 | rtl8xxxu_write32(priv, REG_HISR1, val: 0xffffffff); |
4250 | } else if (priv->rtl_chip == RTL8188E) { |
4251 | rtl8xxxu_write32(priv, REG_HISR0, val: 0xffffffff); |
4252 | val32 = IMR0_PSTIMEOUT | IMR0_TBDER | IMR0_CPWM | IMR0_CPWM2; |
4253 | rtl8xxxu_write32(priv, REG_HIMR0, val: val32); |
4254 | val32 = IMR1_TXERR | IMR1_RXERR | IMR1_TXFOVW | IMR1_RXFOVW; |
4255 | rtl8xxxu_write32(priv, REG_HIMR1, val: val32); |
4256 | val8 = rtl8xxxu_read8(priv, REG_USB_SPECIAL_OPTION); |
4257 | val8 |= USB_SPEC_INT_BULK_SELECT; |
4258 | rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val: val8); |
4259 | } else if (priv->rtl_chip == RTL8710B) { |
4260 | rtl8xxxu_write32(priv, REG_HIMR0_8710B, val: 0); |
4261 | } else if (priv->rtl_chip != RTL8192F) { |
4262 | /* |
4263 | * Enable all interrupts - not obvious USB needs to do this |
4264 | */ |
4265 | rtl8xxxu_write32(priv, REG_HISR, val: 0xffffffff); |
4266 | rtl8xxxu_write32(priv, REG_HIMR, val: 0xffffffff); |
4267 | } |
4268 | |
4269 | /* |
4270 | * Configure initial WMAC settings |
4271 | */ |
4272 | val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST | |
4273 | RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | |
4274 | RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; |
4275 | rtl8xxxu_write32(priv, REG_RCR, val: val32); |
4276 | priv->regrcr = val32; |
4277 | |
4278 | if (fops->init_reg_rxfltmap) { |
4279 | /* Accept all data frames */ |
4280 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, val: 0xffff); |
4281 | |
4282 | /* |
4283 | * Since ADF is removed from RCR, ps-poll will not be indicate to driver, |
4284 | * RxFilterMap should mask ps-poll to gurantee AP mode can rx ps-poll. |
4285 | */ |
4286 | rtl8xxxu_write16(priv, REG_RXFLTMAP1, val: 0x400); |
4287 | |
4288 | /* Accept all management frames */ |
4289 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, val: 0xffff); |
4290 | } else { |
4291 | /* |
4292 | * Accept all multicast |
4293 | */ |
4294 | rtl8xxxu_write32(priv, REG_MAR, val: 0xffffffff); |
4295 | rtl8xxxu_write32(priv, REG_MAR + 4, val: 0xffffffff); |
4296 | } |
4297 | |
4298 | /* |
4299 | * Init adaptive controls |
4300 | */ |
4301 | val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); |
4302 | val32 &= ~RESPONSE_RATE_BITMAP_ALL; |
4303 | val32 |= RESPONSE_RATE_RRSR_CCK_ONLY_1M; |
4304 | rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val: val32); |
4305 | |
4306 | /* CCK = 0x0a, OFDM = 0x10 */ |
4307 | rtl8xxxu_set_spec_sifs(priv, cck: 0x10, ofdm: 0x10); |
4308 | rtl8xxxu_set_retry(priv, short_retry: 0x30, long_retry: 0x30); |
4309 | rtl8xxxu_set_spec_sifs(priv, cck: 0x0a, ofdm: 0x10); |
4310 | |
4311 | /* |
4312 | * Init EDCA |
4313 | */ |
4314 | rtl8xxxu_write16(priv, REG_MAC_SPEC_SIFS, val: 0x100a); |
4315 | |
4316 | /* Set CCK SIFS */ |
4317 | rtl8xxxu_write16(priv, REG_SIFS_CCK, val: 0x100a); |
4318 | |
4319 | /* Set OFDM SIFS */ |
4320 | rtl8xxxu_write16(priv, REG_SIFS_OFDM, val: 0x100a); |
4321 | |
4322 | /* TXOP */ |
4323 | rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, val: 0x005ea42b); |
4324 | rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, val: 0x0000a44f); |
4325 | rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, val: 0x005ea324); |
4326 | rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, val: 0x002fa226); |
4327 | |
4328 | /* Set data auto rate fallback retry count */ |
4329 | rtl8xxxu_write32(priv, REG_DARFRC, val: 0x00000000); |
4330 | rtl8xxxu_write32(priv, REG_DARFRC + 4, val: 0x10080404); |
4331 | rtl8xxxu_write32(priv, REG_RARFRC, val: 0x04030201); |
4332 | rtl8xxxu_write32(priv, REG_RARFRC + 4, val: 0x08070605); |
4333 | |
4334 | val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL); |
4335 | val8 |= FWHW_TXQ_CTRL_AMPDU_RETRY; |
4336 | rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, val: val8); |
4337 | |
4338 | /* Set ACK timeout */ |
4339 | rtl8xxxu_write8(priv, REG_ACKTO, val: 0x40); |
4340 | |
4341 | /* |
4342 | * Initialize beacon parameters |
4343 | */ |
4344 | val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8); |
4345 | rtl8xxxu_write16(priv, REG_BEACON_CTRL, val: val16); |
4346 | rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, val: 0x6404); |
4347 | if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B && |
4348 | priv->rtl_chip != RTL8192F) |
4349 | /* Firmware will control REG_DRVERLYINT when power saving is enable, */ |
4350 | /* so don't set this register on STA mode. */ |
4351 | rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME); |
4352 | rtl8xxxu_write8(priv, REG_BEACON_DMA_TIME, BEACON_DMA_ATIME_INT_TIME); |
4353 | rtl8xxxu_write16(priv, REG_BEACON_TCFG, val: 0x660F); |
4354 | |
4355 | /* |
4356 | * Initialize burst parameters |
4357 | */ |
4358 | if (priv->fops->init_burst) |
4359 | priv->fops->init_burst(priv); |
4360 | |
4361 | if (fops->init_aggregation) |
4362 | fops->init_aggregation(priv); |
4363 | |
4364 | if (fops->init_reg_pkt_life_time) { |
4365 | rtl8xxxu_write16(priv, REG_PKT_VO_VI_LIFE_TIME, val: 0x0400); /* unit: 256us. 256ms */ |
4366 | rtl8xxxu_write16(priv, REG_PKT_BE_BK_LIFE_TIME, val: 0x0400); /* unit: 256us. 256ms */ |
4367 | } |
4368 | |
4369 | /* |
4370 | * Enable CCK and OFDM block |
4371 | */ |
4372 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
4373 | val32 |= (FPGA_RF_MODE_CCK | FPGA_RF_MODE_OFDM); |
4374 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
4375 | |
4376 | /* |
4377 | * Invalidate all CAM entries - bit 30 is undocumented |
4378 | */ |
4379 | rtl8xxxu_write32(priv, REG_CAM_CMD, CAM_CMD_POLLING | BIT(30)); |
4380 | |
4381 | /* |
4382 | * Start out with default power levels for channel 6, 20MHz |
4383 | */ |
4384 | fops->set_tx_power(priv, 1, false); |
4385 | |
4386 | /* Let the 8051 take control of antenna setting */ |
4387 | if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188F && |
4388 | priv->rtl_chip != RTL8710B) { |
4389 | val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); |
4390 | val8 |= LEDCFG2_DPDT_SELECT; |
4391 | rtl8xxxu_write8(priv, REG_LEDCFG2, val: val8); |
4392 | } |
4393 | |
4394 | rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, val: 0xff); |
4395 | |
4396 | /* Disable BAR - not sure if this has any effect on USB */ |
4397 | rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, val: 0x0201ffff); |
4398 | |
4399 | if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && |
4400 | priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) |
4401 | rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, val: 0); |
4402 | |
4403 | if (fops->init_statistics) |
4404 | fops->init_statistics(priv); |
4405 | |
4406 | if (priv->rtl_chip == RTL8192E) { |
4407 | /* |
4408 | * 0x4c6[3] 1: RTS BW = Data BW |
4409 | * 0: RTS BW depends on CCA / secondary CCA result. |
4410 | */ |
4411 | val8 = rtl8xxxu_read8(priv, REG_QUEUE_CTRL); |
4412 | val8 &= ~BIT(3); |
4413 | rtl8xxxu_write8(priv, REG_QUEUE_CTRL, val: val8); |
4414 | /* |
4415 | * Reset USB mode switch setting |
4416 | */ |
4417 | rtl8xxxu_write8(priv, REG_ACLK_MON, val: 0x00); |
4418 | } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E || |
4419 | priv->rtl_chip == RTL8192F) { |
4420 | /* |
4421 | * Init GPIO settings for 8188f, 8188e, 8192f |
4422 | */ |
4423 | val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG); |
4424 | val8 &= ~GPIO_MUXCFG_IO_SEL_ENBT; |
4425 | rtl8xxxu_write8(priv, REG_GPIO_MUXCFG, val: val8); |
4426 | } |
4427 | |
4428 | if (priv->rtl_chip == RTL8188F) |
4429 | /* CCK PD */ |
4430 | rtl8xxxu_write8(priv, REG_CCK_PD_THRESH, CCK_PD_TYPE1_LV1_TH); |
4431 | |
4432 | fops->phy_lc_calibrate(priv); |
4433 | |
4434 | fops->phy_iq_calibrate(priv); |
4435 | |
4436 | /* |
4437 | * This should enable thermal meter |
4438 | */ |
4439 | if (fops->gen2_thermal_meter) { |
4440 | if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) { |
4441 | val32 = rtl8xxxu_read_rfreg(priv, path: RF_A, RF6052_REG_T_METER_8723B); |
4442 | val32 |= 0x30000; |
4443 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_T_METER_8723B, data: val32); |
4444 | } else { |
4445 | rtl8xxxu_write_rfreg(priv, |
4446 | path: RF_A, RF6052_REG_T_METER_8723B, data: 0x37cf8); |
4447 | } |
4448 | } else { |
4449 | rtl8xxxu_write_rfreg(priv, path: RF_A, RF6052_REG_T_METER, data: 0x60); |
4450 | } |
4451 | |
4452 | /* Set NAV_UPPER to 30000us */ |
4453 | val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); |
4454 | rtl8xxxu_write8(priv, REG_NAV_UPPER, val: val8); |
4455 | |
4456 | if (priv->rtl_chip == RTL8723A) { |
4457 | /* |
4458 | * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, |
4459 | * but we need to find root cause. |
4460 | * This is 8723au only. |
4461 | */ |
4462 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
4463 | if ((val32 & 0xff000000) != 0x83000000) { |
4464 | val32 |= FPGA_RF_MODE_CCK; |
4465 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val: val32); |
4466 | } |
4467 | } else if (priv->rtl_chip == RTL8192E || priv->rtl_chip == RTL8188E) { |
4468 | rtl8xxxu_write8(priv, REG_USB_HRPWM, val: 0x00); |
4469 | } |
4470 | |
4471 | val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); |
4472 | val32 |= FWHW_TXQ_CTRL_XMIT_MGMT_ACK; |
4473 | /* ack for xmit mgmt frames. */ |
4474 | rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val: val32); |
4475 | |
4476 | if (priv->rtl_chip == RTL8192E) { |
4477 | /* |
4478 | * Fix LDPC rx hang issue. |
4479 | */ |
4480 | val32 = rtl8xxxu_read32(priv, REG_AFE_MISC); |
4481 | rtl8xxxu_write8(priv, REG_8192E_LDOV12_CTRL, val: 0x75); |
4482 | val32 &= 0xfff00fff; |
4483 | val32 |= 0x0007e000; |
4484 | rtl8xxxu_write32(priv, REG_AFE_MISC, val: val32); |
4485 | |
4486 | /* |
4487 | * 0x824[9] = 0x82C[9] = 0xA80[7] those registers setting |
4488 | * should be equal or CCK RSSI report may be incorrect |
4489 | */ |
4490 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); |
4491 | priv->cck_agc_report_type = |
4492 | u32_get_bits(v: val32, FPGA0_HSSI_PARM2_CCK_HIGH_PWR); |
4493 | |
4494 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_HSSI_PARM2); |
4495 | if (priv->cck_agc_report_type != |
4496 | u32_get_bits(v: val32, FPGA0_HSSI_PARM2_CCK_HIGH_PWR)) { |
4497 | if (priv->cck_agc_report_type) |
4498 | val32 |= FPGA0_HSSI_PARM2_CCK_HIGH_PWR; |
4499 | else |
4500 | val32 &= ~FPGA0_HSSI_PARM2_CCK_HIGH_PWR; |
4501 | rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM2, val: val32); |
4502 | } |
4503 | |
4504 | val32 = rtl8xxxu_read32(priv, REG_AGC_RPT); |
4505 | if (priv->cck_agc_report_type) |
4506 | val32 |= AGC_RPT_CCK; |
4507 | else |
4508 | val32 &= ~AGC_RPT_CCK; |
4509 | rtl8xxxu_write32(priv, REG_AGC_RPT, val: val32); |
4510 | } |
4511 | |
4512 | if (priv->rtl_chip == RTL8710B) { |
4513 | /* |
4514 | * 0x76D[5:4] is Port0,Port1 Enable Bit. |
4515 | * This is only for 8710B, 2b'00 for MP and 2b'11 for Normal Driver |
4516 | */ |
4517 | val8 = rtl8xxxu_read8(priv, REG_PORT_CONTROL_8710B); |
4518 | val8 |= BIT(5) | BIT(4); |
4519 | rtl8xxxu_write8(priv, REG_PORT_CONTROL_8710B, val: val8); |
4520 | |
4521 | /* Set 0x5c[8] and [2:0] = 1, LDO mode */ |
4522 | val32 = rtl8xxxu_read32(priv, REG_WL_RF_PSS_8710B); |
4523 | val32 |= 0x107; |
4524 | rtl8xxxu_write32(priv, REG_WL_RF_PSS_8710B, val: val32); |
4525 | } |
4526 | |
4527 | val32 = rtl8xxxu_read32(priv, addr: 0xa9c); |
4528 | priv->cck_new_agc = u32_get_bits(v: val32, BIT(17)); |
4529 | |
4530 | /* Initialise the center frequency offset tracking */ |
4531 | if (priv->fops->set_crystal_cap) { |
4532 | val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING); |
4533 | priv->cfo_tracking.atc_status = val32 & CFO_TRACKING_ATC_STATUS; |
4534 | priv->cfo_tracking.adjust = true; |
4535 | priv->cfo_tracking.crystal_cap = priv->default_crystal_cap; |
4536 | } |
4537 | |
4538 | if (priv->rtl_chip == RTL8188E) |
4539 | rtl8188e_ra_info_init_all(ra: &priv->ra_info); |
4540 | |
4541 | set_bit(RTL8XXXU_BC_MC_MACID, addr: priv->mac_id_map); |
4542 | set_bit(RTL8XXXU_BC_MC_MACID1, addr: priv->mac_id_map); |
4543 | |
4544 | exit: |
4545 | return ret; |
4546 | } |
4547 | |
4548 | static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, |
4549 | struct ieee80211_key_conf *key, const u8 *mac) |
4550 | { |
4551 | u32 cmd, val32, addr, ctrl; |
4552 | int j, i, tmp_debug; |
4553 | |
4554 | tmp_debug = rtl8xxxu_debug; |
4555 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_KEY) |
4556 | rtl8xxxu_debug |= RTL8XXXU_DEBUG_REG_WRITE; |
4557 | |
4558 | /* |
4559 | * This is a bit of a hack - the lower bits of the cipher |
4560 | * suite selector happens to match the cipher index in the CAM |
4561 | */ |
4562 | addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT; |
4563 | ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID; |
4564 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
4565 | ctrl |= BIT(6); |
4566 | |
4567 | for (j = 5; j >= 0; j--) { |
4568 | switch (j) { |
4569 | case 0: |
4570 | val32 = ctrl | (mac[0] << 16) | (mac[1] << 24); |
4571 | break; |
4572 | case 1: |
4573 | val32 = mac[2] | (mac[3] << 8) | |
4574 | (mac[4] << 16) | (mac[5] << 24); |
4575 | break; |
4576 | default: |
4577 | i = (j - 2) << 2; |
4578 | val32 = key->key[i] | (key->key[i + 1] << 8) | |
4579 | key->key[i + 2] << 16 | key->key[i + 3] << 24; |
4580 | break; |
4581 | } |
4582 | |
4583 | rtl8xxxu_write32(priv, REG_CAM_WRITE, val: val32); |
4584 | cmd = CAM_CMD_POLLING | CAM_CMD_WRITE | (addr + j); |
4585 | rtl8xxxu_write32(priv, REG_CAM_CMD, val: cmd); |
4586 | udelay(100); |
4587 | } |
4588 | |
4589 | rtl8xxxu_debug = tmp_debug; |
4590 | } |
4591 | |
4592 | static |
4593 | int rtl8xxxu_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) |
4594 | { |
4595 | struct rtl8xxxu_priv *priv = hw->priv; |
4596 | |
4597 | *tx_ant = BIT(priv->tx_paths) - 1; |
4598 | *rx_ant = BIT(priv->rx_paths) - 1; |
4599 | |
4600 | return 0; |
4601 | } |
4602 | |
4603 | static int rtl8xxxu_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
4604 | bool set) |
4605 | { |
4606 | struct rtl8xxxu_priv *priv = hw->priv; |
4607 | |
4608 | schedule_delayed_work(dwork: &priv->update_beacon_work, delay: 0); |
4609 | |
4610 | return 0; |
4611 | } |
4612 | |
4613 | static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, |
4614 | struct ieee80211_vif *vif, const u8 *mac) |
4615 | { |
4616 | struct rtl8xxxu_priv *priv = hw->priv; |
4617 | u8 val8; |
4618 | |
4619 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
4620 | val8 |= BEACON_DISABLE_TSF_UPDATE; |
4621 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: val8); |
4622 | } |
4623 | |
4624 | static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, |
4625 | struct ieee80211_vif *vif) |
4626 | { |
4627 | struct rtl8xxxu_priv *priv = hw->priv; |
4628 | u8 val8; |
4629 | |
4630 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
4631 | val8 &= ~BEACON_DISABLE_TSF_UPDATE; |
4632 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: val8); |
4633 | } |
4634 | |
4635 | void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, |
4636 | u32 ramask, u8 rateid, int sgi, int txbw_40mhz, |
4637 | u8 macid) |
4638 | { |
4639 | struct h2c_cmd h2c; |
4640 | |
4641 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4642 | |
4643 | h2c.ramask.cmd = H2C_SET_RATE_MASK; |
4644 | h2c.ramask.mask_lo = cpu_to_le16(ramask & 0xffff); |
4645 | h2c.ramask.mask_hi = cpu_to_le16(ramask >> 16); |
4646 | |
4647 | h2c.ramask.arg = 0x80; |
4648 | if (sgi) |
4649 | h2c.ramask.arg |= 0x20; |
4650 | |
4651 | dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x, size %zi\n" , |
4652 | __func__, ramask, h2c.ramask.arg, sizeof(h2c.ramask)); |
4653 | rtl8xxxu_gen1_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.ramask)); |
4654 | } |
4655 | |
4656 | void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, |
4657 | u32 ramask, u8 rateid, int sgi, int txbw_40mhz, |
4658 | u8 macid) |
4659 | { |
4660 | struct h2c_cmd h2c; |
4661 | u8 bw; |
4662 | |
4663 | if (txbw_40mhz) |
4664 | bw = RTL8XXXU_CHANNEL_WIDTH_40; |
4665 | else |
4666 | bw = RTL8XXXU_CHANNEL_WIDTH_20; |
4667 | |
4668 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4669 | |
4670 | h2c.b_macid_cfg.cmd = H2C_8723B_MACID_CFG_RAID; |
4671 | h2c.b_macid_cfg.ramask0 = ramask & 0xff; |
4672 | h2c.b_macid_cfg.ramask1 = (ramask >> 8) & 0xff; |
4673 | h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff; |
4674 | h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff; |
4675 | h2c.b_macid_cfg.macid = macid; |
4676 | |
4677 | h2c.b_macid_cfg.data1 = rateid; |
4678 | if (sgi) |
4679 | h2c.b_macid_cfg.data1 |= BIT(7); |
4680 | |
4681 | h2c.b_macid_cfg.data2 = bw; |
4682 | |
4683 | dev_dbg(&priv->udev->dev, "%s: rate mask %08x, rateid %02x, sgi %d, size %zi\n" , |
4684 | __func__, ramask, rateid, sgi, sizeof(h2c.b_macid_cfg)); |
4685 | rtl8xxxu_gen2_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.b_macid_cfg)); |
4686 | } |
4687 | |
4688 | void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, |
4689 | u8 macid, u8 role, bool connect) |
4690 | { |
4691 | struct h2c_cmd h2c; |
4692 | |
4693 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4694 | |
4695 | h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT; |
4696 | |
4697 | if (connect) |
4698 | h2c.joinbss.data = H2C_JOIN_BSS_CONNECT; |
4699 | else |
4700 | h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT; |
4701 | |
4702 | rtl8xxxu_gen1_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.joinbss)); |
4703 | } |
4704 | |
4705 | void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, |
4706 | u8 macid, u8 role, bool connect) |
4707 | { |
4708 | /* |
4709 | * The firmware turns on the rate control when it knows it's |
4710 | * connected to a network. |
4711 | */ |
4712 | struct h2c_cmd h2c; |
4713 | |
4714 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4715 | |
4716 | h2c.media_status_rpt.cmd = H2C_8723B_MEDIA_STATUS_RPT; |
4717 | if (connect) |
4718 | h2c.media_status_rpt.parm |= BIT(0); |
4719 | else |
4720 | h2c.media_status_rpt.parm &= ~BIT(0); |
4721 | |
4722 | h2c.media_status_rpt.parm |= ((role << 4) & 0xf0); |
4723 | h2c.media_status_rpt.macid = macid; |
4724 | |
4725 | rtl8xxxu_gen2_h2c_cmd(priv, h2c: &h2c, len: sizeof(h2c.media_status_rpt)); |
4726 | } |
4727 | |
4728 | void (struct rtl8xxxu_priv *priv, u8 macid, u8 ) |
4729 | { |
4730 | struct h2c_cmd h2c; |
4731 | const int h2c_size = 4; |
4732 | |
4733 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4734 | |
4735 | h2c.rssi_report.cmd = H2C_SET_RSSI; |
4736 | h2c.rssi_report.macid = macid; |
4737 | h2c.rssi_report.rssi = rssi; |
4738 | |
4739 | rtl8xxxu_gen1_h2c_cmd(priv, h2c: &h2c, len: h2c_size); |
4740 | } |
4741 | |
4742 | void (struct rtl8xxxu_priv *priv, u8 macid, u8 ) |
4743 | { |
4744 | struct h2c_cmd h2c; |
4745 | int h2c_size = sizeof(h2c.rssi_report); |
4746 | |
4747 | if (priv->rtl_chip == RTL8723B) |
4748 | h2c_size = 4; |
4749 | |
4750 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
4751 | |
4752 | h2c.rssi_report.cmd = H2C_8723B_RSSI_SETTING; |
4753 | h2c.rssi_report.macid = macid; |
4754 | h2c.rssi_report.rssi = rssi; |
4755 | |
4756 | rtl8xxxu_gen2_h2c_cmd(priv, h2c: &h2c, len: h2c_size); |
4757 | } |
4758 | |
4759 | void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv) |
4760 | { |
4761 | u8 agg_ctrl, usb_spec, page_thresh, timeout; |
4762 | |
4763 | usb_spec = rtl8xxxu_read8(priv, REG_USB_SPECIAL_OPTION); |
4764 | usb_spec &= ~USB_SPEC_USB_AGG_ENABLE; |
4765 | rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val: usb_spec); |
4766 | |
4767 | agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL); |
4768 | agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN; |
4769 | |
4770 | if (!rtl8xxxu_dma_aggregation) { |
4771 | rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, val: agg_ctrl); |
4772 | return; |
4773 | } |
4774 | |
4775 | agg_ctrl |= TRXDMA_CTRL_RXDMA_AGG_EN; |
4776 | rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, val: agg_ctrl); |
4777 | |
4778 | /* |
4779 | * The number of packets we can take looks to be buffer size / 512 |
4780 | * which matches the 512 byte rounding we have to do when de-muxing |
4781 | * the packets. |
4782 | * |
4783 | * Sample numbers from the vendor driver: |
4784 | * USB High-Speed mode values: |
4785 | * RxAggBlockCount = 8 : 512 byte unit |
4786 | * RxAggBlockTimeout = 6 |
4787 | * RxAggPageCount = 48 : 128 byte unit |
4788 | * RxAggPageTimeout = 4 or 6 (absolute time 34ms/(2^6)) |
4789 | */ |
4790 | |
4791 | page_thresh = (priv->fops->rx_agg_buf_size / 512); |
4792 | if (rtl8xxxu_dma_agg_pages >= 0) { |
4793 | if (rtl8xxxu_dma_agg_pages <= page_thresh) |
4794 | timeout = page_thresh; |
4795 | else if (rtl8xxxu_dma_agg_pages <= 6) |
4796 | dev_err(&priv->udev->dev, |
4797 | "%s: dma_agg_pages=%i too small, minimum is 6\n" , |
4798 | __func__, rtl8xxxu_dma_agg_pages); |
4799 | else |
4800 | dev_err(&priv->udev->dev, |
4801 | "%s: dma_agg_pages=%i larger than limit %i\n" , |
4802 | __func__, rtl8xxxu_dma_agg_pages, page_thresh); |
4803 | } |
4804 | rtl8xxxu_write8(priv, REG_RXDMA_AGG_PG_TH, val: page_thresh); |
4805 | /* |
4806 | * REG_RXDMA_AGG_PG_TH + 1 seems to be the timeout register on |
4807 | * gen2 chips and rtl8188eu. The rtl8723au seems unhappy if we |
4808 | * don't set it, so better set both. |
4809 | */ |
4810 | timeout = 4; |
4811 | |
4812 | if (rtl8xxxu_dma_agg_timeout >= 0) { |
4813 | if (rtl8xxxu_dma_agg_timeout <= 127) |
4814 | timeout = rtl8xxxu_dma_agg_timeout; |
4815 | else |
4816 | dev_err(&priv->udev->dev, |
4817 | "%s: Invalid dma_agg_timeout: %i\n" , |
4818 | __func__, rtl8xxxu_dma_agg_timeout); |
4819 | } |
4820 | |
4821 | rtl8xxxu_write8(priv, REG_RXDMA_AGG_PG_TH + 1, val: timeout); |
4822 | rtl8xxxu_write8(priv, REG_USB_DMA_AGG_TO, val: timeout); |
4823 | priv->rx_buf_aggregation = 1; |
4824 | } |
4825 | |
4826 | static const struct ieee80211_rate rtl8xxxu_legacy_ratetable[] = { |
4827 | {.bitrate = 10, .hw_value = 0x00,}, |
4828 | {.bitrate = 20, .hw_value = 0x01,}, |
4829 | {.bitrate = 55, .hw_value = 0x02,}, |
4830 | {.bitrate = 110, .hw_value = 0x03,}, |
4831 | {.bitrate = 60, .hw_value = 0x04,}, |
4832 | {.bitrate = 90, .hw_value = 0x05,}, |
4833 | {.bitrate = 120, .hw_value = 0x06,}, |
4834 | {.bitrate = 180, .hw_value = 0x07,}, |
4835 | {.bitrate = 240, .hw_value = 0x08,}, |
4836 | {.bitrate = 360, .hw_value = 0x09,}, |
4837 | {.bitrate = 480, .hw_value = 0x0a,}, |
4838 | {.bitrate = 540, .hw_value = 0x0b,}, |
4839 | }; |
4840 | |
4841 | static void rtl8xxxu_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) |
4842 | { |
4843 | if (rate <= DESC_RATE_54M) |
4844 | return; |
4845 | |
4846 | if (rate >= DESC_RATE_MCS0 && rate <= DESC_RATE_MCS15) { |
4847 | if (rate < DESC_RATE_MCS8) |
4848 | *nss = 1; |
4849 | else |
4850 | *nss = 2; |
4851 | *mcs = rate - DESC_RATE_MCS0; |
4852 | } |
4853 | } |
4854 | |
4855 | static void rtl8xxxu_set_basic_rates(struct rtl8xxxu_priv *priv, u32 rate_cfg) |
4856 | { |
4857 | struct ieee80211_hw *hw = priv->hw; |
4858 | u32 val32; |
4859 | u8 rate_idx = 0; |
4860 | |
4861 | rate_cfg &= RESPONSE_RATE_BITMAP_ALL; |
4862 | |
4863 | val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); |
4864 | if (hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) |
4865 | val32 &= RESPONSE_RATE_RRSR_INIT_5G; |
4866 | else |
4867 | val32 &= RESPONSE_RATE_RRSR_INIT_2G; |
4868 | val32 |= rate_cfg; |
4869 | rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val: val32); |
4870 | |
4871 | dev_dbg(&priv->udev->dev, "%s: rates %08x\n" , __func__, rate_cfg); |
4872 | |
4873 | if (rate_cfg) |
4874 | rate_idx = __fls(word: rate_cfg); |
4875 | |
4876 | rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, val: rate_idx); |
4877 | } |
4878 | |
4879 | static u16 |
4880 | rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta) |
4881 | { |
4882 | u16 network_type = WIRELESS_MODE_UNKNOWN; |
4883 | |
4884 | if (hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) { |
4885 | if (sta->deflink.vht_cap.vht_supported) |
4886 | network_type = WIRELESS_MODE_AC; |
4887 | else if (sta->deflink.ht_cap.ht_supported) |
4888 | network_type = WIRELESS_MODE_N_5G; |
4889 | |
4890 | network_type |= WIRELESS_MODE_A; |
4891 | } else { |
4892 | if (sta->deflink.vht_cap.vht_supported) |
4893 | network_type = WIRELESS_MODE_AC; |
4894 | else if (sta->deflink.ht_cap.ht_supported) |
4895 | network_type = WIRELESS_MODE_N_24G; |
4896 | |
4897 | if (sta->deflink.supp_rates[0] <= 0xf) |
4898 | network_type |= WIRELESS_MODE_B; |
4899 | else if (sta->deflink.supp_rates[0] & 0xf) |
4900 | network_type |= (WIRELESS_MODE_B | WIRELESS_MODE_G); |
4901 | else |
4902 | network_type |= WIRELESS_MODE_G; |
4903 | } |
4904 | |
4905 | return network_type; |
4906 | } |
4907 | |
4908 | static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time) |
4909 | { |
4910 | u32 reg_edca_param[IEEE80211_NUM_ACS] = { |
4911 | [IEEE80211_AC_VO] = REG_EDCA_VO_PARAM, |
4912 | [IEEE80211_AC_VI] = REG_EDCA_VI_PARAM, |
4913 | [IEEE80211_AC_BE] = REG_EDCA_BE_PARAM, |
4914 | [IEEE80211_AC_BK] = REG_EDCA_BK_PARAM, |
4915 | }; |
4916 | u32 val32; |
4917 | u16 wireless_mode = 0; |
4918 | u8 aifs, aifsn, sifs; |
4919 | int i; |
4920 | |
4921 | for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) { |
4922 | struct ieee80211_sta *sta; |
4923 | |
4924 | if (!priv->vifs[i]) |
4925 | continue; |
4926 | |
4927 | rcu_read_lock(); |
4928 | sta = ieee80211_find_sta(vif: priv->vifs[i], addr: priv->vifs[i]->bss_conf.bssid); |
4929 | if (sta) |
4930 | wireless_mode = rtl8xxxu_wireless_mode(hw: priv->hw, sta); |
4931 | rcu_read_unlock(); |
4932 | |
4933 | if (wireless_mode) |
4934 | break; |
4935 | } |
4936 | |
4937 | if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ || |
4938 | (wireless_mode & WIRELESS_MODE_N_24G)) |
4939 | sifs = 16; |
4940 | else |
4941 | sifs = 10; |
4942 | |
4943 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
4944 | val32 = rtl8xxxu_read32(priv, addr: reg_edca_param[i]); |
4945 | |
4946 | /* It was set in conf_tx. */ |
4947 | aifsn = val32 & 0xff; |
4948 | |
4949 | /* aifsn not set yet or already fixed */ |
4950 | if (aifsn < 2 || aifsn > 15) |
4951 | continue; |
4952 | |
4953 | aifs = aifsn * slot_time + sifs; |
4954 | |
4955 | val32 &= ~0xff; |
4956 | val32 |= aifs; |
4957 | rtl8xxxu_write32(priv, addr: reg_edca_param[i], val: val32); |
4958 | } |
4959 | } |
4960 | |
4961 | void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, |
4962 | u8 rate, u8 sgi, u8 bw) |
4963 | { |
4964 | u8 mcs, nss; |
4965 | |
4966 | rarpt->txrate.flags = 0; |
4967 | |
4968 | if (rate <= DESC_RATE_54M) { |
4969 | rarpt->txrate.legacy = rtl8xxxu_legacy_ratetable[rate].bitrate; |
4970 | } else { |
4971 | rtl8xxxu_desc_to_mcsrate(rate, mcs: &mcs, nss: &nss); |
4972 | rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS; |
4973 | |
4974 | rarpt->txrate.mcs = mcs; |
4975 | rarpt->txrate.nss = nss; |
4976 | |
4977 | if (sgi) |
4978 | rarpt->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
4979 | |
4980 | rarpt->txrate.bw = bw; |
4981 | } |
4982 | |
4983 | rarpt->bit_rate = cfg80211_calculate_bitrate(rate: &rarpt->txrate); |
4984 | rarpt->desc_rate = rate; |
4985 | } |
4986 | |
4987 | static void |
4988 | rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
4989 | struct ieee80211_bss_conf *bss_conf, u64 changed) |
4990 | { |
4991 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
4992 | struct rtl8xxxu_priv *priv = hw->priv; |
4993 | struct device *dev = &priv->udev->dev; |
4994 | struct rtl8xxxu_sta_info *sta_info; |
4995 | struct ieee80211_sta *sta; |
4996 | struct rtl8xxxu_ra_report *rarpt; |
4997 | u8 val8, macid; |
4998 | u32 val32; |
4999 | |
5000 | rarpt = &priv->ra_report; |
5001 | |
5002 | if (changed & BSS_CHANGED_ASSOC) { |
5003 | dev_dbg(dev, "Changed ASSOC: %i!\n" , vif->cfg.assoc); |
5004 | |
5005 | rtl8xxxu_set_linktype(priv, linktype: vif->type, port_num: rtlvif->port_num); |
5006 | |
5007 | if (vif->cfg.assoc) { |
5008 | u32 ramask; |
5009 | int sgi = 0; |
5010 | u8 highest_rate; |
5011 | u8 bw; |
5012 | |
5013 | rcu_read_lock(); |
5014 | sta = ieee80211_find_sta(vif, addr: bss_conf->bssid); |
5015 | if (!sta) { |
5016 | dev_info(dev, "%s: ASSOC no sta found\n" , |
5017 | __func__); |
5018 | rcu_read_unlock(); |
5019 | goto error; |
5020 | } |
5021 | macid = rtl8xxxu_get_macid(priv, sta); |
5022 | |
5023 | if (sta->deflink.ht_cap.ht_supported) |
5024 | dev_info(dev, "%s: HT supported\n" , __func__); |
5025 | if (sta->deflink.vht_cap.vht_supported) |
5026 | dev_info(dev, "%s: VHT supported\n" , __func__); |
5027 | |
5028 | /* TODO: Set bits 28-31 for rate adaptive id */ |
5029 | ramask = (sta->deflink.supp_rates[0] & 0xfff) | |
5030 | sta->deflink.ht_cap.mcs.rx_mask[0] << 12 | |
5031 | sta->deflink.ht_cap.mcs.rx_mask[1] << 20; |
5032 | if (sta->deflink.ht_cap.cap & |
5033 | (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) |
5034 | sgi = 1; |
5035 | |
5036 | highest_rate = fls(x: ramask) - 1; |
5037 | if (rtl8xxxu_ht40_2g && |
5038 | (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
5039 | bw = RATE_INFO_BW_40; |
5040 | else |
5041 | bw = RATE_INFO_BW_20; |
5042 | |
5043 | sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
5044 | sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT; |
5045 | rcu_read_unlock(); |
5046 | |
5047 | rtl8xxxu_update_ra_report(rarpt, rate: highest_rate, sgi, bw); |
5048 | |
5049 | priv->fops->update_rate_mask(priv, ramask, 0, sgi, |
5050 | bw == RATE_INFO_BW_40, macid); |
5051 | |
5052 | rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, val: 0xff); |
5053 | |
5054 | if (rtlvif->port_num == 0) |
5055 | rtl8xxxu_stop_tx_beacon(priv); |
5056 | |
5057 | /* joinbss sequence */ |
5058 | rtl8xxxu_write16(priv, REG_BCN_PSR_RPT, |
5059 | val: 0xc000 | vif->cfg.aid); |
5060 | |
5061 | priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, true); |
5062 | } else { |
5063 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
5064 | val8 |= BEACON_DISABLE_TSF_UPDATE; |
5065 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: val8); |
5066 | |
5067 | priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, false); |
5068 | } |
5069 | } |
5070 | |
5071 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
5072 | dev_dbg(dev, "Changed ERP_PREAMBLE: Use short preamble %i\n" , |
5073 | bss_conf->use_short_preamble); |
5074 | val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); |
5075 | if (bss_conf->use_short_preamble) |
5076 | val32 |= RSR_ACK_SHORT_PREAMBLE; |
5077 | else |
5078 | val32 &= ~RSR_ACK_SHORT_PREAMBLE; |
5079 | rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val: val32); |
5080 | } |
5081 | |
5082 | if (changed & BSS_CHANGED_ERP_SLOT) { |
5083 | dev_dbg(dev, "Changed ERP_SLOT: short_slot_time %i\n" , |
5084 | bss_conf->use_short_slot); |
5085 | |
5086 | if (bss_conf->use_short_slot) |
5087 | val8 = 9; |
5088 | else |
5089 | val8 = 20; |
5090 | rtl8xxxu_write8(priv, REG_SLOT, val: val8); |
5091 | |
5092 | rtl8xxxu_set_aifs(priv, slot_time: val8); |
5093 | } |
5094 | |
5095 | if (changed & BSS_CHANGED_BSSID) { |
5096 | dev_dbg(dev, "Changed BSSID!\n" ); |
5097 | rtl8xxxu_set_bssid(priv, bssid: bss_conf->bssid, port_num: rtlvif->port_num); |
5098 | } |
5099 | |
5100 | if (changed & BSS_CHANGED_BASIC_RATES) { |
5101 | dev_dbg(dev, "Changed BASIC_RATES!\n" ); |
5102 | rtl8xxxu_set_basic_rates(priv, rate_cfg: bss_conf->basic_rates); |
5103 | } |
5104 | |
5105 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
5106 | if (bss_conf->enable_beacon) |
5107 | rtl8xxxu_start_tx_beacon(priv); |
5108 | else |
5109 | rtl8xxxu_stop_tx_beacon(priv); |
5110 | } |
5111 | |
5112 | if (changed & BSS_CHANGED_BEACON) |
5113 | schedule_delayed_work(dwork: &priv->update_beacon_work, delay: 0); |
5114 | |
5115 | error: |
5116 | return; |
5117 | } |
5118 | |
5119 | static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
5120 | struct ieee80211_bss_conf *link_conf) |
5121 | { |
5122 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
5123 | struct rtl8xxxu_priv *priv = hw->priv; |
5124 | struct device *dev = &priv->udev->dev; |
5125 | |
5126 | dev_dbg(dev, "Start AP mode\n" ); |
5127 | rtl8xxxu_set_bssid(priv, bssid: vif->bss_conf.bssid, port_num: rtlvif->port_num); |
5128 | rtl8xxxu_write16(priv, REG_BCN_INTERVAL, val: vif->bss_conf.beacon_int); |
5129 | priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true); |
5130 | |
5131 | return 0; |
5132 | } |
5133 | |
5134 | static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue) |
5135 | { |
5136 | u32 rtlqueue; |
5137 | |
5138 | switch (queue) { |
5139 | case IEEE80211_AC_VO: |
5140 | rtlqueue = TXDESC_QUEUE_VO; |
5141 | break; |
5142 | case IEEE80211_AC_VI: |
5143 | rtlqueue = TXDESC_QUEUE_VI; |
5144 | break; |
5145 | case IEEE80211_AC_BE: |
5146 | rtlqueue = TXDESC_QUEUE_BE; |
5147 | break; |
5148 | case IEEE80211_AC_BK: |
5149 | rtlqueue = TXDESC_QUEUE_BK; |
5150 | break; |
5151 | default: |
5152 | rtlqueue = TXDESC_QUEUE_BE; |
5153 | } |
5154 | |
5155 | return rtlqueue; |
5156 | } |
5157 | |
5158 | static u32 rtl8xxxu_queue_select(struct ieee80211_hdr *hdr, struct sk_buff *skb) |
5159 | { |
5160 | u32 queue; |
5161 | |
5162 | if (unlikely(ieee80211_is_beacon(hdr->frame_control))) |
5163 | queue = TXDESC_QUEUE_BEACON; |
5164 | else if (ieee80211_is_mgmt(fc: hdr->frame_control)) |
5165 | queue = TXDESC_QUEUE_MGNT; |
5166 | else |
5167 | queue = rtl8xxxu_80211_to_rtl_queue(queue: skb_get_queue_mapping(skb)); |
5168 | |
5169 | return queue; |
5170 | } |
5171 | |
5172 | /* |
5173 | * Despite newer chips 8723b/8812/8821 having a larger TX descriptor |
5174 | * format. The descriptor checksum is still only calculated over the |
5175 | * initial 32 bytes of the descriptor! |
5176 | */ |
5177 | static void rtl8xxxu_calc_tx_desc_csum(struct rtl8xxxu_txdesc32 *tx_desc) |
5178 | { |
5179 | __le16 *ptr = (__le16 *)tx_desc; |
5180 | u16 csum = 0; |
5181 | int i; |
5182 | |
5183 | /* |
5184 | * Clear csum field before calculation, as the csum field is |
5185 | * in the middle of the struct. |
5186 | */ |
5187 | tx_desc->csum = cpu_to_le16(0); |
5188 | |
5189 | for (i = 0; i < (sizeof(struct rtl8xxxu_txdesc32) / sizeof(u16)); i++) |
5190 | csum = csum ^ le16_to_cpu(ptr[i]); |
5191 | |
5192 | tx_desc->csum |= cpu_to_le16(csum); |
5193 | } |
5194 | |
5195 | static void rtl8xxxu_free_tx_resources(struct rtl8xxxu_priv *priv) |
5196 | { |
5197 | struct rtl8xxxu_tx_urb *tx_urb, *tmp; |
5198 | unsigned long flags; |
5199 | |
5200 | spin_lock_irqsave(&priv->tx_urb_lock, flags); |
5201 | list_for_each_entry_safe(tx_urb, tmp, &priv->tx_urb_free_list, list) { |
5202 | list_del(entry: &tx_urb->list); |
5203 | priv->tx_urb_free_count--; |
5204 | usb_free_urb(urb: &tx_urb->urb); |
5205 | } |
5206 | spin_unlock_irqrestore(lock: &priv->tx_urb_lock, flags); |
5207 | } |
5208 | |
5209 | static struct rtl8xxxu_tx_urb * |
5210 | rtl8xxxu_alloc_tx_urb(struct rtl8xxxu_priv *priv) |
5211 | { |
5212 | struct rtl8xxxu_tx_urb *tx_urb; |
5213 | unsigned long flags; |
5214 | |
5215 | spin_lock_irqsave(&priv->tx_urb_lock, flags); |
5216 | tx_urb = list_first_entry_or_null(&priv->tx_urb_free_list, |
5217 | struct rtl8xxxu_tx_urb, list); |
5218 | if (tx_urb) { |
5219 | list_del(entry: &tx_urb->list); |
5220 | priv->tx_urb_free_count--; |
5221 | if (priv->tx_urb_free_count < RTL8XXXU_TX_URB_LOW_WATER && |
5222 | !priv->tx_stopped) { |
5223 | priv->tx_stopped = true; |
5224 | ieee80211_stop_queues(hw: priv->hw); |
5225 | } |
5226 | } |
5227 | |
5228 | spin_unlock_irqrestore(lock: &priv->tx_urb_lock, flags); |
5229 | |
5230 | return tx_urb; |
5231 | } |
5232 | |
5233 | static void rtl8xxxu_free_tx_urb(struct rtl8xxxu_priv *priv, |
5234 | struct rtl8xxxu_tx_urb *tx_urb) |
5235 | { |
5236 | unsigned long flags; |
5237 | |
5238 | INIT_LIST_HEAD(list: &tx_urb->list); |
5239 | |
5240 | spin_lock_irqsave(&priv->tx_urb_lock, flags); |
5241 | |
5242 | list_add(new: &tx_urb->list, head: &priv->tx_urb_free_list); |
5243 | priv->tx_urb_free_count++; |
5244 | if (priv->tx_urb_free_count > RTL8XXXU_TX_URB_HIGH_WATER && |
5245 | priv->tx_stopped) { |
5246 | priv->tx_stopped = false; |
5247 | ieee80211_wake_queues(hw: priv->hw); |
5248 | } |
5249 | |
5250 | spin_unlock_irqrestore(lock: &priv->tx_urb_lock, flags); |
5251 | } |
5252 | |
5253 | static void rtl8xxxu_tx_complete(struct urb *urb) |
5254 | { |
5255 | struct sk_buff *skb = (struct sk_buff *)urb->context; |
5256 | struct ieee80211_tx_info *tx_info; |
5257 | struct ieee80211_hw *hw; |
5258 | struct rtl8xxxu_priv *priv; |
5259 | struct rtl8xxxu_tx_urb *tx_urb = |
5260 | container_of(urb, struct rtl8xxxu_tx_urb, urb); |
5261 | |
5262 | tx_info = IEEE80211_SKB_CB(skb); |
5263 | hw = tx_info->rate_driver_data[0]; |
5264 | priv = hw->priv; |
5265 | |
5266 | skb_pull(skb, len: priv->fops->tx_desc_size); |
5267 | |
5268 | ieee80211_tx_info_clear_status(info: tx_info); |
5269 | tx_info->status.rates[0].idx = -1; |
5270 | tx_info->status.rates[0].count = 0; |
5271 | |
5272 | if (!urb->status) |
5273 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
5274 | |
5275 | ieee80211_tx_status_irqsafe(hw, skb); |
5276 | |
5277 | rtl8xxxu_free_tx_urb(priv, tx_urb); |
5278 | } |
5279 | |
5280 | static void rtl8xxxu_dump_action(struct device *dev, |
5281 | struct ieee80211_hdr *hdr) |
5282 | { |
5283 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; |
5284 | u16 cap, timeout; |
5285 | |
5286 | if (!(rtl8xxxu_debug & RTL8XXXU_DEBUG_ACTION)) |
5287 | return; |
5288 | |
5289 | switch (mgmt->u.action.u.addba_resp.action_code) { |
5290 | case WLAN_ACTION_ADDBA_RESP: |
5291 | cap = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
5292 | timeout = le16_to_cpu(mgmt->u.action.u.addba_resp.timeout); |
5293 | dev_info(dev, "WLAN_ACTION_ADDBA_RESP: " |
5294 | "timeout %i, tid %02x, buf_size %02x, policy %02x, " |
5295 | "status %02x\n" , |
5296 | timeout, |
5297 | (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, |
5298 | (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, |
5299 | (cap >> 1) & 0x1, |
5300 | le16_to_cpu(mgmt->u.action.u.addba_resp.status)); |
5301 | break; |
5302 | case WLAN_ACTION_ADDBA_REQ: |
5303 | cap = le16_to_cpu(mgmt->u.action.u.addba_req.capab); |
5304 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); |
5305 | dev_info(dev, "WLAN_ACTION_ADDBA_REQ: " |
5306 | "timeout %i, tid %02x, buf_size %02x, policy %02x\n" , |
5307 | timeout, |
5308 | (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, |
5309 | (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, |
5310 | (cap >> 1) & 0x1); |
5311 | break; |
5312 | default: |
5313 | dev_info(dev, "action frame %02x\n" , |
5314 | mgmt->u.action.u.addba_resp.action_code); |
5315 | break; |
5316 | } |
5317 | } |
5318 | |
5319 | /* |
5320 | * Fill in v1 (gen1) specific TX descriptor bits. |
5321 | * This format is used on 8188cu/8192cu/8723au |
5322 | */ |
5323 | void |
5324 | rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
5325 | struct ieee80211_tx_info *tx_info, |
5326 | struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, |
5327 | bool short_preamble, bool ampdu_enable, u32 rts_rate, |
5328 | u8 macid) |
5329 | { |
5330 | struct rtl8xxxu_priv *priv = hw->priv; |
5331 | struct device *dev = &priv->udev->dev; |
5332 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
5333 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
5334 | u32 rate = 0; |
5335 | u16 seq_number; |
5336 | |
5337 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) |
5338 | dev_info(dev, "%s: TX rate: %d, pkt size %u\n" , |
5339 | __func__, rate, le16_to_cpu(tx_desc->pkt_size)); |
5340 | |
5341 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
5342 | |
5343 | tx_desc->txdw5 = cpu_to_le32(rate); |
5344 | |
5345 | if (ieee80211_is_data(fc: hdr->frame_control)) |
5346 | tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); |
5347 | |
5348 | tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT); |
5349 | |
5350 | if (ampdu_enable && test_bit(tid, priv->tid_tx_operational)) |
5351 | tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_ENABLE); |
5352 | else |
5353 | tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_BREAK); |
5354 | |
5355 | if (ieee80211_is_mgmt(fc: hdr->frame_control)) { |
5356 | tx_desc->txdw5 = cpu_to_le32(rate); |
5357 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE); |
5358 | tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT); |
5359 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE); |
5360 | } |
5361 | |
5362 | if (ieee80211_is_data_qos(fc: hdr->frame_control)) |
5363 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_QOS); |
5364 | |
5365 | if (short_preamble) |
5366 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE); |
5367 | |
5368 | if (sgi) |
5369 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); |
5370 | |
5371 | /* |
5372 | * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled |
5373 | */ |
5374 | tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT); |
5375 | if (ampdu_enable || tx_info->control.use_rts) { |
5376 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); |
5377 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); |
5378 | } else if (tx_info->control.use_cts_prot) { |
5379 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE); |
5380 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); |
5381 | } |
5382 | } |
5383 | |
5384 | /* |
5385 | * Fill in v2 (gen2) specific TX descriptor bits. |
5386 | * This format is used on 8192eu/8723bu |
5387 | */ |
5388 | void |
5389 | rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
5390 | struct ieee80211_tx_info *tx_info, |
5391 | struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, |
5392 | bool short_preamble, bool ampdu_enable, u32 rts_rate, |
5393 | u8 macid) |
5394 | { |
5395 | struct rtl8xxxu_priv *priv = hw->priv; |
5396 | struct device *dev = &priv->udev->dev; |
5397 | struct rtl8xxxu_txdesc40 *tx_desc40; |
5398 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
5399 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
5400 | u32 rate = 0; |
5401 | u16 seq_number; |
5402 | |
5403 | tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32; |
5404 | |
5405 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) |
5406 | dev_info(dev, "%s: TX rate: %d, pkt size %u\n" , |
5407 | __func__, rate, le16_to_cpu(tx_desc40->pkt_size)); |
5408 | |
5409 | tx_desc40->txdw1 |= cpu_to_le32(macid << TXDESC40_MACID_SHIFT); |
5410 | |
5411 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
5412 | |
5413 | tx_desc40->txdw4 = cpu_to_le32(rate); |
5414 | if (ieee80211_is_data(fc: hdr->frame_control)) { |
5415 | tx_desc40->txdw4 |= cpu_to_le32(0x1f << |
5416 | TXDESC40_DATA_RATE_FB_SHIFT); |
5417 | } |
5418 | |
5419 | tx_desc40->txdw9 = cpu_to_le32((u32)seq_number << TXDESC40_SEQ_SHIFT); |
5420 | |
5421 | if (ampdu_enable && test_bit(tid, priv->tid_tx_operational)) |
5422 | tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE); |
5423 | else |
5424 | tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK); |
5425 | |
5426 | if (ieee80211_is_mgmt(fc: hdr->frame_control)) { |
5427 | tx_desc40->txdw4 = cpu_to_le32(rate); |
5428 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_USE_DRIVER_RATE); |
5429 | tx_desc40->txdw4 |= |
5430 | cpu_to_le32(6 << TXDESC40_RETRY_LIMIT_SHIFT); |
5431 | tx_desc40->txdw4 |= cpu_to_le32(TXDESC40_RETRY_LIMIT_ENABLE); |
5432 | } |
5433 | |
5434 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) |
5435 | tx_desc40->txdw8 |= cpu_to_le32(TXDESC40_HW_SEQ_ENABLE); |
5436 | |
5437 | if (short_preamble) |
5438 | tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE); |
5439 | |
5440 | tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT); |
5441 | |
5442 | /* |
5443 | * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled |
5444 | */ |
5445 | if (ampdu_enable || tx_info->control.use_rts) { |
5446 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE); |
5447 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE); |
5448 | } else if (tx_info->control.use_cts_prot) { |
5449 | /* |
5450 | * For some reason the vendor driver doesn't set |
5451 | * TXDESC40_HW_RTS_ENABLE for CTS to SELF |
5452 | */ |
5453 | tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_CTS_SELF_ENABLE); |
5454 | } |
5455 | } |
5456 | |
5457 | /* |
5458 | * Fill in v3 (gen1) specific TX descriptor bits. |
5459 | * This format is a hybrid between the v1 and v2 formats, only seen |
5460 | * on 8188eu devices so far. |
5461 | */ |
5462 | void |
5463 | rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, |
5464 | struct ieee80211_tx_info *tx_info, |
5465 | struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, |
5466 | bool short_preamble, bool ampdu_enable, u32 rts_rate, |
5467 | u8 macid) |
5468 | { |
5469 | struct rtl8xxxu_priv *priv = hw->priv; |
5470 | struct device *dev = &priv->udev->dev; |
5471 | struct rtl8xxxu_ra_info *ra = &priv->ra_info; |
5472 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
5473 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
5474 | u32 rate = 0; |
5475 | u16 seq_number; |
5476 | |
5477 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
5478 | |
5479 | if (ieee80211_is_data(fc: hdr->frame_control)) { |
5480 | rate = ra->decision_rate; |
5481 | tx_desc->txdw5 = cpu_to_le32(rate); |
5482 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE); |
5483 | tx_desc->txdw4 |= le32_encode_bits(v: ra->pt_stage, TXDESC32_PT_STAGE_MASK); |
5484 | /* Data/RTS rate FB limit */ |
5485 | tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); |
5486 | } |
5487 | |
5488 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) |
5489 | dev_info(dev, "%s: TX rate: %d, pkt size %d\n" , |
5490 | __func__, rate, le16_to_cpu(tx_desc->pkt_size)); |
5491 | |
5492 | tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT); |
5493 | |
5494 | if (ampdu_enable && test_bit(tid, priv->tid_tx_operational)) |
5495 | tx_desc->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE); |
5496 | else |
5497 | tx_desc->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK); |
5498 | |
5499 | if (ieee80211_is_mgmt(fc: hdr->frame_control)) { |
5500 | tx_desc->txdw5 = cpu_to_le32(rate); |
5501 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_USE_DRIVER_RATE); |
5502 | tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC32_RETRY_LIMIT_SHIFT); |
5503 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE); |
5504 | } |
5505 | |
5506 | if (ieee80211_is_data_qos(fc: hdr->frame_control)) { |
5507 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_QOS); |
5508 | |
5509 | if (conf_is_ht40(conf: &hw->conf)) { |
5510 | tx_desc->txdw4 |= cpu_to_le32(TXDESC_DATA_BW); |
5511 | |
5512 | if (conf_is_ht40_minus(conf: &hw->conf)) |
5513 | tx_desc->txdw4 |= cpu_to_le32(TXDESC_PRIME_CH_OFF_UPPER); |
5514 | else |
5515 | tx_desc->txdw4 |= cpu_to_le32(TXDESC_PRIME_CH_OFF_LOWER); |
5516 | } |
5517 | } |
5518 | |
5519 | if (short_preamble) |
5520 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE); |
5521 | |
5522 | if (sgi && ra->rate_sgi) |
5523 | tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI); |
5524 | |
5525 | /* |
5526 | * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled |
5527 | */ |
5528 | tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT); |
5529 | if (ampdu_enable || tx_info->control.use_rts) { |
5530 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); |
5531 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); |
5532 | } else if (tx_info->control.use_cts_prot) { |
5533 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE); |
5534 | tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); |
5535 | } |
5536 | |
5537 | tx_desc->txdw2 |= cpu_to_le32(TXDESC_ANTENNA_SELECT_A | |
5538 | TXDESC_ANTENNA_SELECT_B); |
5539 | tx_desc->txdw7 |= cpu_to_le16(TXDESC_ANTENNA_SELECT_C >> 16); |
5540 | } |
5541 | |
5542 | static void rtl8xxxu_tx(struct ieee80211_hw *hw, |
5543 | struct ieee80211_tx_control *control, |
5544 | struct sk_buff *skb) |
5545 | { |
5546 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
5547 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
5548 | struct rtl8xxxu_priv *priv = hw->priv; |
5549 | struct rtl8xxxu_txdesc32 *tx_desc; |
5550 | struct rtl8xxxu_tx_urb *tx_urb; |
5551 | struct ieee80211_sta *sta = NULL; |
5552 | struct ieee80211_vif *vif = tx_info->control.vif; |
5553 | struct rtl8xxxu_vif *rtlvif = vif ? (struct rtl8xxxu_vif *)vif->drv_priv : NULL; |
5554 | struct device *dev = &priv->udev->dev; |
5555 | u32 queue, rts_rate; |
5556 | u16 pktlen = skb->len; |
5557 | int tx_desc_size = priv->fops->tx_desc_size; |
5558 | u8 macid; |
5559 | int ret; |
5560 | bool ampdu_enable, sgi = false, short_preamble = false, bmc = false; |
5561 | |
5562 | if (skb_headroom(skb) < tx_desc_size) { |
5563 | dev_warn(dev, |
5564 | "%s: Not enough headroom (%i) for tx descriptor\n" , |
5565 | __func__, skb_headroom(skb)); |
5566 | goto error; |
5567 | } |
5568 | |
5569 | if (unlikely(skb->len > (65535 - tx_desc_size))) { |
5570 | dev_warn(dev, "%s: Trying to send over-sized skb (%i)\n" , |
5571 | __func__, skb->len); |
5572 | goto error; |
5573 | } |
5574 | |
5575 | tx_urb = rtl8xxxu_alloc_tx_urb(priv); |
5576 | if (!tx_urb) { |
5577 | dev_warn(dev, "%s: Unable to allocate tx urb\n" , __func__); |
5578 | goto error; |
5579 | } |
5580 | |
5581 | if (ieee80211_is_action(fc: hdr->frame_control)) |
5582 | rtl8xxxu_dump_action(dev, hdr); |
5583 | |
5584 | tx_info->rate_driver_data[0] = hw; |
5585 | |
5586 | if (control && control->sta) |
5587 | sta = control->sta; |
5588 | |
5589 | queue = rtl8xxxu_queue_select(hdr, skb); |
5590 | |
5591 | tx_desc = skb_push(skb, len: tx_desc_size); |
5592 | |
5593 | memset(tx_desc, 0, tx_desc_size); |
5594 | tx_desc->pkt_size = cpu_to_le16(pktlen); |
5595 | tx_desc->pkt_offset = tx_desc_size; |
5596 | |
5597 | /* These bits mean different things to the RTL8192F. */ |
5598 | if (priv->rtl_chip != RTL8192F) |
5599 | tx_desc->txdw0 = |
5600 | TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; |
5601 | if (is_multicast_ether_addr(addr: ieee80211_get_DA(hdr)) || |
5602 | is_broadcast_ether_addr(addr: ieee80211_get_DA(hdr))) { |
5603 | tx_desc->txdw0 |= TXDESC_BROADMULTICAST; |
5604 | bmc = true; |
5605 | } |
5606 | |
5607 | |
5608 | tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); |
5609 | macid = rtl8xxxu_get_macid(priv, sta); |
5610 | |
5611 | if (tx_info->control.hw_key) { |
5612 | switch (tx_info->control.hw_key->cipher) { |
5613 | case WLAN_CIPHER_SUITE_WEP40: |
5614 | case WLAN_CIPHER_SUITE_WEP104: |
5615 | case WLAN_CIPHER_SUITE_TKIP: |
5616 | tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_RC4); |
5617 | break; |
5618 | case WLAN_CIPHER_SUITE_CCMP: |
5619 | tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_AES); |
5620 | break; |
5621 | default: |
5622 | break; |
5623 | } |
5624 | if (bmc && rtlvif && rtlvif->hw_key_idx != 0xff) { |
5625 | tx_desc->txdw1 |= cpu_to_le32(TXDESC_EN_DESC_ID); |
5626 | macid = rtlvif->hw_key_idx; |
5627 | } |
5628 | } |
5629 | |
5630 | /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */ |
5631 | ampdu_enable = false; |
5632 | if (ieee80211_is_data_qos(fc: hdr->frame_control) && sta) { |
5633 | if (sta->deflink.ht_cap.ht_supported) { |
5634 | u32 ampdu, val32; |
5635 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
5636 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
5637 | |
5638 | ampdu = (u32)sta->deflink.ht_cap.ampdu_density; |
5639 | val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT; |
5640 | tx_desc->txdw2 |= cpu_to_le32(val32); |
5641 | |
5642 | ampdu_enable = true; |
5643 | |
5644 | if (!test_bit(tid, priv->tx_aggr_started) && |
5645 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) |
5646 | if (!ieee80211_start_tx_ba_session(sta, tid, timeout: 0)) |
5647 | set_bit(nr: tid, addr: priv->tx_aggr_started); |
5648 | } |
5649 | } |
5650 | |
5651 | if (ieee80211_is_data_qos(fc: hdr->frame_control) && |
5652 | sta && sta->deflink.ht_cap.cap & |
5653 | (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) |
5654 | sgi = true; |
5655 | |
5656 | if (sta && vif && vif->bss_conf.use_short_preamble) |
5657 | short_preamble = true; |
5658 | |
5659 | if (skb->len > hw->wiphy->rts_threshold) |
5660 | tx_info->control.use_rts = true; |
5661 | |
5662 | if (sta && vif && vif->bss_conf.use_cts_prot) |
5663 | tx_info->control.use_cts_prot = true; |
5664 | |
5665 | if (ampdu_enable || tx_info->control.use_rts || |
5666 | tx_info->control.use_cts_prot) |
5667 | rts_rate = DESC_RATE_24M; |
5668 | else |
5669 | rts_rate = 0; |
5670 | |
5671 | priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, |
5672 | ampdu_enable, rts_rate, macid); |
5673 | |
5674 | rtl8xxxu_calc_tx_desc_csum(tx_desc); |
5675 | |
5676 | /* avoid zero checksum make tx hang */ |
5677 | if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) |
5678 | tx_desc->csum = ~tx_desc->csum; |
5679 | |
5680 | usb_fill_bulk_urb(urb: &tx_urb->urb, dev: priv->udev, pipe: priv->pipe_out[queue], |
5681 | transfer_buffer: skb->data, buffer_length: skb->len, complete_fn: rtl8xxxu_tx_complete, context: skb); |
5682 | |
5683 | usb_anchor_urb(urb: &tx_urb->urb, anchor: &priv->tx_anchor); |
5684 | ret = usb_submit_urb(urb: &tx_urb->urb, GFP_ATOMIC); |
5685 | if (ret) { |
5686 | usb_unanchor_urb(urb: &tx_urb->urb); |
5687 | rtl8xxxu_free_tx_urb(priv, tx_urb); |
5688 | goto error; |
5689 | } |
5690 | return; |
5691 | error: |
5692 | dev_kfree_skb(skb); |
5693 | } |
5694 | |
5695 | static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw, |
5696 | struct ieee80211_vif *vif) |
5697 | { |
5698 | struct rtl8xxxu_priv *priv = hw->priv; |
5699 | struct sk_buff *skb = ieee80211_beacon_get(hw, vif, link_id: 0); |
5700 | struct device *dev = &priv->udev->dev; |
5701 | int retry; |
5702 | u8 val8; |
5703 | |
5704 | /* BCN_VALID, write 1 to clear, cleared by SW */ |
5705 | val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2); |
5706 | val8 |= BIT_BCN_VALID >> 16; |
5707 | rtl8xxxu_write8(priv, REG_TDECTRL + 2, val: val8); |
5708 | |
5709 | /* SW_BCN_SEL - Port0 */ |
5710 | val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2); |
5711 | val8 &= ~(BIT_SW_BCN_SEL >> 16); |
5712 | rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B + 2, val: val8); |
5713 | |
5714 | if (skb) |
5715 | rtl8xxxu_tx(hw, NULL, skb); |
5716 | |
5717 | retry = 100; |
5718 | do { |
5719 | val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2); |
5720 | if (val8 & (BIT_BCN_VALID >> 16)) |
5721 | break; |
5722 | usleep_range(min: 10, max: 20); |
5723 | } while (--retry); |
5724 | |
5725 | if (!retry) |
5726 | dev_err(dev, "%s: Failed to read beacon valid bit\n" , __func__); |
5727 | } |
5728 | |
5729 | static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work) |
5730 | { |
5731 | struct rtl8xxxu_priv *priv = |
5732 | container_of(work, struct rtl8xxxu_priv, update_beacon_work.work); |
5733 | struct ieee80211_hw *hw = priv->hw; |
5734 | struct ieee80211_vif *vif = priv->vifs[0]; |
5735 | |
5736 | if (!vif) { |
5737 | WARN_ONCE(true, "no vif to update beacon\n" ); |
5738 | return; |
5739 | } |
5740 | |
5741 | if (vif->bss_conf.csa_active) { |
5742 | if (ieee80211_beacon_cntdwn_is_complete(vif, link_id: 0)) { |
5743 | ieee80211_csa_finish(vif, link_id: 0); |
5744 | return; |
5745 | } |
5746 | schedule_delayed_work(dwork: &priv->update_beacon_work, |
5747 | delay: msecs_to_jiffies(m: vif->bss_conf.beacon_int)); |
5748 | } |
5749 | rtl8xxxu_send_beacon_frame(hw, vif); |
5750 | } |
5751 | |
5752 | static inline bool rtl8xxxu_is_packet_match_bssid(struct rtl8xxxu_priv *priv, |
5753 | struct ieee80211_hdr *hdr, |
5754 | int port_num) |
5755 | { |
5756 | return priv->vifs[port_num] && |
5757 | priv->vifs[port_num]->type == NL80211_IFTYPE_STATION && |
5758 | priv->vifs[port_num]->cfg.assoc && |
5759 | ether_addr_equal(addr1: priv->vifs[port_num]->bss_conf.bssid, addr2: hdr->addr2); |
5760 | } |
5761 | |
5762 | static inline bool rtl8xxxu_is_sta_sta(struct rtl8xxxu_priv *priv) |
5763 | { |
5764 | return (priv->vifs[0] && priv->vifs[0]->cfg.assoc && |
5765 | priv->vifs[0]->type == NL80211_IFTYPE_STATION) && |
5766 | (priv->vifs[1] && priv->vifs[1]->cfg.assoc && |
5767 | priv->vifs[1]->type == NL80211_IFTYPE_STATION); |
5768 | } |
5769 | |
5770 | void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv, |
5771 | struct ieee80211_rx_status *rx_status, |
5772 | struct rtl8723au_phy_stats *phy_stats, |
5773 | u32 rxmcs, struct ieee80211_hdr *hdr, |
5774 | bool crc_icv_err) |
5775 | { |
5776 | if (phy_stats->sgi_en) |
5777 | rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; |
5778 | |
5779 | if (rxmcs < DESC_RATE_6M) { |
5780 | /* |
5781 | * Handle PHY stats for CCK rates |
5782 | */ |
5783 | rx_status->signal = priv->fops->cck_rssi(priv, phy_stats); |
5784 | } else { |
5785 | bool parse_cfo = priv->fops->set_crystal_cap && |
5786 | !crc_icv_err && |
5787 | !ieee80211_is_ctl(fc: hdr->frame_control) && |
5788 | !rtl8xxxu_is_sta_sta(priv) && |
5789 | (rtl8xxxu_is_packet_match_bssid(priv, hdr, port_num: 0) || |
5790 | rtl8xxxu_is_packet_match_bssid(priv, hdr, port_num: 1)); |
5791 | |
5792 | if (parse_cfo) { |
5793 | priv->cfo_tracking.cfo_tail[0] = phy_stats->path_cfotail[0]; |
5794 | priv->cfo_tracking.cfo_tail[1] = phy_stats->path_cfotail[1]; |
5795 | |
5796 | priv->cfo_tracking.packet_count++; |
5797 | } |
5798 | |
5799 | rx_status->signal = |
5800 | (phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110; |
5801 | } |
5802 | } |
5803 | |
5804 | static void jaguar2_rx_parse_phystats_type0(struct rtl8xxxu_priv *priv, |
5805 | struct ieee80211_rx_status *rx_status, |
5806 | struct jaguar2_phy_stats_type0 *phy_stats0, |
5807 | u32 rxmcs, struct ieee80211_hdr *hdr, |
5808 | bool crc_icv_err) |
5809 | { |
5810 | s8 rx_power = phy_stats0->pwdb - 110; |
5811 | |
5812 | if (!priv->cck_new_agc) |
5813 | rx_power = priv->fops->cck_rssi(priv, (struct rtl8723au_phy_stats *)phy_stats0); |
5814 | |
5815 | rx_status->signal = rx_power; |
5816 | } |
5817 | |
5818 | static void jaguar2_rx_parse_phystats_type1(struct rtl8xxxu_priv *priv, |
5819 | struct ieee80211_rx_status *rx_status, |
5820 | struct jaguar2_phy_stats_type1 *phy_stats1, |
5821 | u32 rxmcs, struct ieee80211_hdr *hdr, |
5822 | bool crc_icv_err) |
5823 | { |
5824 | bool parse_cfo = priv->fops->set_crystal_cap && |
5825 | !crc_icv_err && |
5826 | !ieee80211_is_ctl(fc: hdr->frame_control) && |
5827 | !rtl8xxxu_is_sta_sta(priv) && |
5828 | (rtl8xxxu_is_packet_match_bssid(priv, hdr, port_num: 0) || |
5829 | rtl8xxxu_is_packet_match_bssid(priv, hdr, port_num: 1)); |
5830 | u8 pwdb_max = 0; |
5831 | int rx_path; |
5832 | |
5833 | if (parse_cfo) { |
5834 | /* Only path-A and path-B have CFO tail and short CFO */ |
5835 | priv->cfo_tracking.cfo_tail[RF_A] = phy_stats1->cfo_tail[RF_A]; |
5836 | priv->cfo_tracking.cfo_tail[RF_B] = phy_stats1->cfo_tail[RF_B]; |
5837 | |
5838 | priv->cfo_tracking.packet_count++; |
5839 | } |
5840 | |
5841 | for (rx_path = 0; rx_path < priv->rx_paths; rx_path++) |
5842 | pwdb_max = max(pwdb_max, phy_stats1->pwdb[rx_path]); |
5843 | |
5844 | rx_status->signal = pwdb_max - 110; |
5845 | } |
5846 | |
5847 | static void jaguar2_rx_parse_phystats_type2(struct rtl8xxxu_priv *priv, |
5848 | struct ieee80211_rx_status *rx_status, |
5849 | struct jaguar2_phy_stats_type2 *phy_stats2, |
5850 | u32 rxmcs, struct ieee80211_hdr *hdr, |
5851 | bool crc_icv_err) |
5852 | { |
5853 | u8 pwdb_max = 0; |
5854 | int rx_path; |
5855 | |
5856 | for (rx_path = 0; rx_path < priv->rx_paths; rx_path++) |
5857 | pwdb_max = max(pwdb_max, phy_stats2->pwdb[rx_path]); |
5858 | |
5859 | rx_status->signal = pwdb_max - 110; |
5860 | } |
5861 | |
5862 | void jaguar2_rx_parse_phystats(struct rtl8xxxu_priv *priv, |
5863 | struct ieee80211_rx_status *rx_status, |
5864 | struct rtl8723au_phy_stats *phy_stats, |
5865 | u32 rxmcs, struct ieee80211_hdr *hdr, |
5866 | bool crc_icv_err) |
5867 | { |
5868 | struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats; |
5869 | struct jaguar2_phy_stats_type1 *phy_stats1 = (struct jaguar2_phy_stats_type1 *)phy_stats; |
5870 | struct jaguar2_phy_stats_type2 *phy_stats2 = (struct jaguar2_phy_stats_type2 *)phy_stats; |
5871 | |
5872 | switch (phy_stats0->page_num) { |
5873 | case 0: |
5874 | /* CCK */ |
5875 | jaguar2_rx_parse_phystats_type0(priv, rx_status, phy_stats0, |
5876 | rxmcs, hdr, crc_icv_err); |
5877 | break; |
5878 | case 1: |
5879 | /* OFDM */ |
5880 | jaguar2_rx_parse_phystats_type1(priv, rx_status, phy_stats1, |
5881 | rxmcs, hdr, crc_icv_err); |
5882 | break; |
5883 | case 2: |
5884 | /* Also OFDM but different (how?) */ |
5885 | jaguar2_rx_parse_phystats_type2(priv, rx_status, phy_stats2, |
5886 | rxmcs, hdr, crc_icv_err); |
5887 | break; |
5888 | default: |
5889 | return; |
5890 | } |
5891 | } |
5892 | |
5893 | static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv) |
5894 | { |
5895 | struct rtl8xxxu_rx_urb *rx_urb, *tmp; |
5896 | unsigned long flags; |
5897 | |
5898 | spin_lock_irqsave(&priv->rx_urb_lock, flags); |
5899 | |
5900 | list_for_each_entry_safe(rx_urb, tmp, |
5901 | &priv->rx_urb_pending_list, list) { |
5902 | list_del(entry: &rx_urb->list); |
5903 | priv->rx_urb_pending_count--; |
5904 | usb_free_urb(urb: &rx_urb->urb); |
5905 | } |
5906 | |
5907 | spin_unlock_irqrestore(lock: &priv->rx_urb_lock, flags); |
5908 | } |
5909 | |
5910 | static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv, |
5911 | struct rtl8xxxu_rx_urb *rx_urb) |
5912 | { |
5913 | struct sk_buff *skb; |
5914 | unsigned long flags; |
5915 | int pending = 0; |
5916 | |
5917 | spin_lock_irqsave(&priv->rx_urb_lock, flags); |
5918 | |
5919 | if (!priv->shutdown) { |
5920 | list_add_tail(new: &rx_urb->list, head: &priv->rx_urb_pending_list); |
5921 | priv->rx_urb_pending_count++; |
5922 | pending = priv->rx_urb_pending_count; |
5923 | } else { |
5924 | skb = (struct sk_buff *)rx_urb->urb.context; |
5925 | dev_kfree_skb_irq(skb); |
5926 | usb_free_urb(urb: &rx_urb->urb); |
5927 | } |
5928 | |
5929 | spin_unlock_irqrestore(lock: &priv->rx_urb_lock, flags); |
5930 | |
5931 | if (pending > RTL8XXXU_RX_URB_PENDING_WATER) |
5932 | schedule_work(work: &priv->rx_urb_wq); |
5933 | } |
5934 | |
5935 | static void rtl8xxxu_rx_urb_work(struct work_struct *work) |
5936 | { |
5937 | struct rtl8xxxu_priv *priv; |
5938 | struct rtl8xxxu_rx_urb *rx_urb, *tmp; |
5939 | struct list_head local; |
5940 | struct sk_buff *skb; |
5941 | unsigned long flags; |
5942 | int ret; |
5943 | |
5944 | priv = container_of(work, struct rtl8xxxu_priv, rx_urb_wq); |
5945 | INIT_LIST_HEAD(list: &local); |
5946 | |
5947 | spin_lock_irqsave(&priv->rx_urb_lock, flags); |
5948 | |
5949 | list_splice_init(list: &priv->rx_urb_pending_list, head: &local); |
5950 | priv->rx_urb_pending_count = 0; |
5951 | |
5952 | spin_unlock_irqrestore(lock: &priv->rx_urb_lock, flags); |
5953 | |
5954 | list_for_each_entry_safe(rx_urb, tmp, &local, list) { |
5955 | list_del_init(entry: &rx_urb->list); |
5956 | ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); |
5957 | /* |
5958 | * If out of memory or temporary error, put it back on the |
5959 | * queue and try again. Otherwise the device is dead/gone |
5960 | * and we should drop it. |
5961 | */ |
5962 | switch (ret) { |
5963 | case 0: |
5964 | break; |
5965 | case -ENOMEM: |
5966 | case -EAGAIN: |
5967 | rtl8xxxu_queue_rx_urb(priv, rx_urb); |
5968 | break; |
5969 | default: |
5970 | dev_warn(&priv->udev->dev, |
5971 | "failed to requeue urb with error %i\n" , ret); |
5972 | skb = (struct sk_buff *)rx_urb->urb.context; |
5973 | dev_kfree_skb(skb); |
5974 | usb_free_urb(urb: &rx_urb->urb); |
5975 | } |
5976 | } |
5977 | } |
5978 | |
5979 | /* |
5980 | * The RTL8723BU/RTL8192EU vendor driver use coexistence table type |
5981 | * 0-7 to represent writing different combinations of register values |
5982 | * to REG_BT_COEX_TABLEs. It's for different kinds of coexistence use |
5983 | * cases which Realtek doesn't provide detail for these settings. Keep |
5984 | * this aligned with vendor driver for easier maintenance. |
5985 | */ |
5986 | static |
5987 | void rtl8723bu_set_coex_with_type(struct rtl8xxxu_priv *priv, u8 type) |
5988 | { |
5989 | switch (type) { |
5990 | case 0: |
5991 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x55555555); |
5992 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0x55555555); |
5993 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
5994 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
5995 | break; |
5996 | case 1: |
5997 | case 3: |
5998 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x55555555); |
5999 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0x5a5a5a5a); |
6000 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6001 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6002 | break; |
6003 | case 2: |
6004 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x5a5a5a5a); |
6005 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0x5a5a5a5a); |
6006 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6007 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6008 | break; |
6009 | case 4: |
6010 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x5a5a5a5a); |
6011 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0xaaaa5a5a); |
6012 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6013 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6014 | break; |
6015 | case 5: |
6016 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x5a5a5a5a); |
6017 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0xaa5a5a5a); |
6018 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6019 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6020 | break; |
6021 | case 6: |
6022 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0x55555555); |
6023 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0xaaaaaaaa); |
6024 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6025 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6026 | break; |
6027 | case 7: |
6028 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, val: 0xaaaaaaaa); |
6029 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, val: 0xaaaaaaaa); |
6030 | rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, val: 0x00ffffff); |
6031 | rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, val: 0x03); |
6032 | break; |
6033 | default: |
6034 | break; |
6035 | } |
6036 | } |
6037 | |
6038 | static |
6039 | void rtl8723bu_update_bt_link_info(struct rtl8xxxu_priv *priv, u8 bt_info) |
6040 | { |
6041 | struct rtl8xxxu_btcoex *btcoex = &priv->bt_coex; |
6042 | |
6043 | if (bt_info & BT_INFO_8723B_1ANT_B_INQ_PAGE) |
6044 | btcoex->c2h_bt_inquiry = true; |
6045 | else |
6046 | btcoex->c2h_bt_inquiry = false; |
6047 | |
6048 | if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) { |
6049 | btcoex->bt_status = BT_8723B_1ANT_STATUS_NON_CONNECTED_IDLE; |
6050 | btcoex->has_sco = false; |
6051 | btcoex->has_hid = false; |
6052 | btcoex->has_pan = false; |
6053 | btcoex->has_a2dp = false; |
6054 | } else { |
6055 | if ((bt_info & 0x1f) == BT_INFO_8723B_1ANT_B_CONNECTION) |
6056 | btcoex->bt_status = BT_8723B_1ANT_STATUS_CONNECTED_IDLE; |
6057 | else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) || |
6058 | (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY)) |
6059 | btcoex->bt_status = BT_8723B_1ANT_STATUS_SCO_BUSY; |
6060 | else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) |
6061 | btcoex->bt_status = BT_8723B_1ANT_STATUS_ACL_BUSY; |
6062 | else |
6063 | btcoex->bt_status = BT_8723B_1ANT_STATUS_MAX; |
6064 | |
6065 | if (bt_info & BT_INFO_8723B_1ANT_B_FTP) |
6066 | btcoex->has_pan = true; |
6067 | else |
6068 | btcoex->has_pan = false; |
6069 | |
6070 | if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) |
6071 | btcoex->has_a2dp = true; |
6072 | else |
6073 | btcoex->has_a2dp = false; |
6074 | |
6075 | if (bt_info & BT_INFO_8723B_1ANT_B_HID) |
6076 | btcoex->has_hid = true; |
6077 | else |
6078 | btcoex->has_hid = false; |
6079 | |
6080 | if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) |
6081 | btcoex->has_sco = true; |
6082 | else |
6083 | btcoex->has_sco = false; |
6084 | } |
6085 | |
6086 | if (!btcoex->has_a2dp && !btcoex->has_sco && |
6087 | !btcoex->has_pan && btcoex->has_hid) |
6088 | btcoex->hid_only = true; |
6089 | else |
6090 | btcoex->hid_only = false; |
6091 | |
6092 | if (!btcoex->has_sco && !btcoex->has_pan && |
6093 | !btcoex->has_hid && btcoex->has_a2dp) |
6094 | btcoex->has_a2dp = true; |
6095 | else |
6096 | btcoex->has_a2dp = false; |
6097 | |
6098 | if (btcoex->bt_status == BT_8723B_1ANT_STATUS_SCO_BUSY || |
6099 | btcoex->bt_status == BT_8723B_1ANT_STATUS_ACL_BUSY) |
6100 | btcoex->bt_busy = true; |
6101 | else |
6102 | btcoex->bt_busy = false; |
6103 | } |
6104 | |
6105 | static inline bool rtl8xxxu_is_assoc(struct rtl8xxxu_priv *priv) |
6106 | { |
6107 | return (priv->vifs[0] && priv->vifs[0]->cfg.assoc) || |
6108 | (priv->vifs[1] && priv->vifs[1]->cfg.assoc); |
6109 | } |
6110 | |
6111 | static |
6112 | void rtl8723bu_handle_bt_inquiry(struct rtl8xxxu_priv *priv) |
6113 | { |
6114 | struct rtl8xxxu_btcoex *btcoex; |
6115 | |
6116 | btcoex = &priv->bt_coex; |
6117 | |
6118 | if (!rtl8xxxu_is_assoc(priv)) { |
6119 | rtl8723bu_set_ps_tdma(priv, arg1: 0x8, arg2: 0x0, arg3: 0x0, arg4: 0x0, arg5: 0x0); |
6120 | rtl8723bu_set_coex_with_type(priv, type: 0); |
6121 | } else if (btcoex->has_sco || btcoex->has_hid || btcoex->has_a2dp) { |
6122 | rtl8723bu_set_ps_tdma(priv, arg1: 0x61, arg2: 0x35, arg3: 0x3, arg4: 0x11, arg5: 0x11); |
6123 | rtl8723bu_set_coex_with_type(priv, type: 4); |
6124 | } else if (btcoex->has_pan) { |
6125 | rtl8723bu_set_ps_tdma(priv, arg1: 0x61, arg2: 0x3f, arg3: 0x3, arg4: 0x11, arg5: 0x11); |
6126 | rtl8723bu_set_coex_with_type(priv, type: 4); |
6127 | } else { |
6128 | rtl8723bu_set_ps_tdma(priv, arg1: 0x8, arg2: 0x0, arg3: 0x0, arg4: 0x0, arg5: 0x0); |
6129 | rtl8723bu_set_coex_with_type(priv, type: 7); |
6130 | } |
6131 | } |
6132 | |
6133 | static |
6134 | void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv) |
6135 | { |
6136 | struct rtl8xxxu_btcoex *btcoex; |
6137 | |
6138 | btcoex = &priv->bt_coex; |
6139 | |
6140 | if (rtl8xxxu_is_assoc(priv)) { |
6141 | u32 val32 = 0; |
6142 | u32 high_prio_tx = 0, high_prio_rx = 0; |
6143 | |
6144 | val32 = rtl8xxxu_read32(priv, addr: 0x770); |
6145 | high_prio_tx = val32 & 0x0000ffff; |
6146 | high_prio_rx = (val32 & 0xffff0000) >> 16; |
6147 | |
6148 | if (btcoex->bt_busy) { |
6149 | if (btcoex->hid_only) { |
6150 | rtl8723bu_set_ps_tdma(priv, arg1: 0x61, arg2: 0x20, |
6151 | arg3: 0x3, arg4: 0x11, arg5: 0x11); |
6152 | rtl8723bu_set_coex_with_type(priv, type: 5); |
6153 | } else if (btcoex->a2dp_only) { |
6154 | rtl8723bu_set_ps_tdma(priv, arg1: 0x61, arg2: 0x35, |
6155 | arg3: 0x3, arg4: 0x11, arg5: 0x11); |
6156 | rtl8723bu_set_coex_with_type(priv, type: 4); |
6157 | } else if ((btcoex->has_a2dp && btcoex->has_pan) || |
6158 | (btcoex->has_hid && btcoex->has_a2dp && |
6159 | btcoex->has_pan)) { |
6160 | rtl8723bu_set_ps_tdma(priv, arg1: 0x51, arg2: 0x21, |
6161 | arg3: 0x3, arg4: 0x10, arg5: 0x10); |
6162 | rtl8723bu_set_coex_with_type(priv, type: 4); |
6163 | } else if (btcoex->has_hid && btcoex->has_a2dp) { |
6164 | rtl8723bu_set_ps_tdma(priv, arg1: 0x51, arg2: 0x21, |
6165 | arg3: 0x3, arg4: 0x10, arg5: 0x10); |
6166 | rtl8723bu_set_coex_with_type(priv, type: 3); |
6167 | } else { |
6168 | rtl8723bu_set_ps_tdma(priv, arg1: 0x61, arg2: 0x35, |
6169 | arg3: 0x3, arg4: 0x11, arg5: 0x11); |
6170 | rtl8723bu_set_coex_with_type(priv, type: 4); |
6171 | } |
6172 | } else { |
6173 | rtl8723bu_set_ps_tdma(priv, arg1: 0x8, arg2: 0x0, arg3: 0x0, arg4: 0x0, arg5: 0x0); |
6174 | if (high_prio_tx + high_prio_rx <= 60) |
6175 | rtl8723bu_set_coex_with_type(priv, type: 2); |
6176 | else |
6177 | rtl8723bu_set_coex_with_type(priv, type: 7); |
6178 | } |
6179 | } else { |
6180 | rtl8723bu_set_ps_tdma(priv, arg1: 0x8, arg2: 0x0, arg3: 0x0, arg4: 0x0, arg5: 0x0); |
6181 | rtl8723bu_set_coex_with_type(priv, type: 0); |
6182 | } |
6183 | } |
6184 | |
6185 | static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) |
6186 | { |
6187 | struct rtl8xxxu_priv *priv; |
6188 | struct rtl8723bu_c2h *c2h; |
6189 | struct sk_buff *skb = NULL; |
6190 | u8 bt_info = 0; |
6191 | struct rtl8xxxu_btcoex *btcoex; |
6192 | struct rtl8xxxu_ra_report *rarpt; |
6193 | u8 bw; |
6194 | |
6195 | priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work); |
6196 | btcoex = &priv->bt_coex; |
6197 | rarpt = &priv->ra_report; |
6198 | |
6199 | while (!skb_queue_empty(list: &priv->c2hcmd_queue)) { |
6200 | skb = skb_dequeue(list: &priv->c2hcmd_queue); |
6201 | |
6202 | c2h = (struct rtl8723bu_c2h *)skb->data; |
6203 | |
6204 | switch (c2h->id) { |
6205 | case C2H_8723B_BT_INFO: |
6206 | bt_info = c2h->bt_info.bt_info; |
6207 | |
6208 | rtl8723bu_update_bt_link_info(priv, bt_info); |
6209 | if (btcoex->c2h_bt_inquiry) { |
6210 | rtl8723bu_handle_bt_inquiry(priv); |
6211 | break; |
6212 | } |
6213 | rtl8723bu_handle_bt_info(priv); |
6214 | break; |
6215 | case C2H_8723B_RA_REPORT: |
6216 | bw = rarpt->txrate.bw; |
6217 | |
6218 | if (skb->len >= offsetofend(typeof(*c2h), ra_report.bw)) { |
6219 | if (c2h->ra_report.bw == RTL8XXXU_CHANNEL_WIDTH_40) |
6220 | bw = RATE_INFO_BW_40; |
6221 | else |
6222 | bw = RATE_INFO_BW_20; |
6223 | } |
6224 | |
6225 | rtl8xxxu_update_ra_report(rarpt, rate: c2h->ra_report.rate, |
6226 | sgi: c2h->ra_report.sgi, bw); |
6227 | break; |
6228 | default: |
6229 | break; |
6230 | } |
6231 | |
6232 | dev_kfree_skb(skb); |
6233 | } |
6234 | } |
6235 | |
6236 | static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, |
6237 | struct sk_buff *skb) |
6238 | { |
6239 | struct rtl8723bu_c2h *c2h = (struct rtl8723bu_c2h *)skb->data; |
6240 | struct device *dev = &priv->udev->dev; |
6241 | int len; |
6242 | |
6243 | len = skb->len - 2; |
6244 | |
6245 | dev_dbg(dev, "C2H ID %02x seq %02x, len %02x source %02x\n" , |
6246 | c2h->id, c2h->seq, len, c2h->bt_info.response_source); |
6247 | |
6248 | switch(c2h->id) { |
6249 | case C2H_8723B_BT_INFO: |
6250 | if (c2h->bt_info.response_source > |
6251 | BT_INFO_SRC_8723B_BT_ACTIVE_SEND) |
6252 | dev_dbg(dev, "C2H_BT_INFO WiFi only firmware\n" ); |
6253 | else |
6254 | dev_dbg(dev, "C2H_BT_INFO BT/WiFi coexist firmware\n" ); |
6255 | |
6256 | if (c2h->bt_info.bt_has_reset) |
6257 | dev_dbg(dev, "BT has been reset\n" ); |
6258 | if (c2h->bt_info.tx_rx_mask) |
6259 | dev_dbg(dev, "BT TRx mask\n" ); |
6260 | |
6261 | break; |
6262 | case C2H_8723B_BT_MP_INFO: |
6263 | dev_dbg(dev, "C2H_MP_INFO ext ID %02x, status %02x\n" , |
6264 | c2h->bt_mp_info.ext_id, c2h->bt_mp_info.status); |
6265 | break; |
6266 | case C2H_8723B_RA_REPORT: |
6267 | dev_dbg(dev, |
6268 | "C2H RA RPT: rate %02x, unk %i, macid %02x, noise %i\n" , |
6269 | c2h->ra_report.rate, c2h->ra_report.sgi, |
6270 | c2h->ra_report.macid, c2h->ra_report.noisy_state); |
6271 | break; |
6272 | default: |
6273 | dev_info(dev, "Unhandled C2H event %02x seq %02x\n" , |
6274 | c2h->id, c2h->seq); |
6275 | print_hex_dump(KERN_INFO, prefix_str: "C2H content: " , prefix_type: DUMP_PREFIX_NONE, |
6276 | rowsize: 16, groupsize: 1, buf: c2h->raw.payload, len, ascii: false); |
6277 | break; |
6278 | } |
6279 | |
6280 | skb_queue_tail(list: &priv->c2hcmd_queue, newsk: skb); |
6281 | |
6282 | schedule_work(work: &priv->c2hcmd_work); |
6283 | } |
6284 | |
6285 | static void rtl8188e_c2hcmd_callback(struct work_struct *work) |
6286 | { |
6287 | struct rtl8xxxu_priv *priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work); |
6288 | struct device *dev = &priv->udev->dev; |
6289 | struct sk_buff *skb = NULL; |
6290 | struct rtl8xxxu_rxdesc16 *rx_desc; |
6291 | |
6292 | while (!skb_queue_empty(list: &priv->c2hcmd_queue)) { |
6293 | skb = skb_dequeue(list: &priv->c2hcmd_queue); |
6294 | |
6295 | rx_desc = (struct rtl8xxxu_rxdesc16 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16)); |
6296 | |
6297 | switch (rx_desc->rpt_sel) { |
6298 | case 1: |
6299 | dev_dbg(dev, "C2H TX report type 1\n" ); |
6300 | |
6301 | break; |
6302 | case 2: |
6303 | dev_dbg(dev, "C2H TX report type 2\n" ); |
6304 | |
6305 | rtl8188e_handle_ra_tx_report2(priv, skb); |
6306 | |
6307 | break; |
6308 | case 3: |
6309 | dev_dbg(dev, "C2H USB interrupt report\n" ); |
6310 | |
6311 | break; |
6312 | default: |
6313 | dev_warn(dev, "%s: rpt_sel should not be %d\n" , |
6314 | __func__, rx_desc->rpt_sel); |
6315 | |
6316 | break; |
6317 | } |
6318 | |
6319 | dev_kfree_skb(skb); |
6320 | } |
6321 | } |
6322 | |
6323 | #define rtl8xxxu_iterate_vifs_atomic(priv, iterator, data) \ |
6324 | ieee80211_iterate_active_interfaces_atomic((priv)->hw, \ |
6325 | IEEE80211_IFACE_ITER_NORMAL, iterator, data) |
6326 | |
6327 | struct { |
6328 | struct rtl8xxxu_priv *; |
6329 | struct ieee80211_hdr *; |
6330 | struct ieee80211_rx_status *; |
6331 | u8 *; |
6332 | }; |
6333 | |
6334 | static void (void *data, u8 *mac, |
6335 | struct ieee80211_vif *vif) |
6336 | { |
6337 | struct rtl8xxxu_rx_update_rssi_data *iter_data = data; |
6338 | struct ieee80211_sta *sta; |
6339 | struct ieee80211_hdr *hdr = iter_data->hdr; |
6340 | struct rtl8xxxu_priv *priv = iter_data->priv; |
6341 | struct rtl8xxxu_sta_info *sta_info; |
6342 | struct ieee80211_rx_status *rx_status = iter_data->rx_status; |
6343 | u8 *bssid = iter_data->bssid; |
6344 | |
6345 | if (!ether_addr_equal(addr1: vif->bss_conf.bssid, addr2: bssid)) |
6346 | return; |
6347 | |
6348 | if (!(ether_addr_equal(addr1: vif->addr, addr2: hdr->addr1) || |
6349 | ieee80211_is_beacon(fc: hdr->frame_control))) |
6350 | return; |
6351 | |
6352 | sta = ieee80211_find_sta_by_ifaddr(hw: priv->hw, addr: hdr->addr2, |
6353 | localaddr: vif->addr); |
6354 | if (!sta) |
6355 | return; |
6356 | |
6357 | sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
6358 | ewma_rssi_add(e: &sta_info->avg_rssi, val: -rx_status->signal); |
6359 | } |
6360 | |
6361 | static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) |
6362 | { |
6363 | __le16 fc = hdr->frame_control; |
6364 | u8 *bssid; |
6365 | |
6366 | if (ieee80211_has_tods(fc)) |
6367 | bssid = hdr->addr1; |
6368 | else if (ieee80211_has_fromds(fc)) |
6369 | bssid = hdr->addr2; |
6370 | else |
6371 | bssid = hdr->addr3; |
6372 | |
6373 | return bssid; |
6374 | } |
6375 | |
6376 | static void (struct rtl8xxxu_priv *priv, |
6377 | struct ieee80211_rx_status *rx_status, |
6378 | struct ieee80211_hdr *hdr) |
6379 | { |
6380 | struct rtl8xxxu_rx_update_rssi_data data = {}; |
6381 | |
6382 | if (ieee80211_is_ctl(fc: hdr->frame_control)) |
6383 | return; |
6384 | |
6385 | data.priv = priv; |
6386 | data.hdr = hdr; |
6387 | data.rx_status = rx_status; |
6388 | data.bssid = get_hdr_bssid(hdr); |
6389 | |
6390 | rtl8xxxu_iterate_vifs_atomic(priv, rtl8xxxu_rx_update_rssi_iter, &data); |
6391 | } |
6392 | |
6393 | int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) |
6394 | { |
6395 | struct ieee80211_hw *hw = priv->hw; |
6396 | struct ieee80211_rx_status *rx_status; |
6397 | struct rtl8xxxu_rxdesc16 *rx_desc; |
6398 | struct rtl8723au_phy_stats *phy_stats; |
6399 | struct sk_buff *next_skb = NULL; |
6400 | __le32 *_rx_desc_le; |
6401 | u32 *_rx_desc; |
6402 | int drvinfo_sz, desc_shift; |
6403 | int i, pkt_cnt, pkt_len, urb_len, pkt_offset; |
6404 | |
6405 | urb_len = skb->len; |
6406 | pkt_cnt = 0; |
6407 | |
6408 | if (urb_len < sizeof(struct rtl8xxxu_rxdesc16)) { |
6409 | kfree_skb(skb); |
6410 | return RX_TYPE_ERROR; |
6411 | } |
6412 | |
6413 | do { |
6414 | rx_desc = (struct rtl8xxxu_rxdesc16 *)skb->data; |
6415 | _rx_desc_le = (__le32 *)skb->data; |
6416 | _rx_desc = (u32 *)skb->data; |
6417 | |
6418 | for (i = 0; |
6419 | i < (sizeof(struct rtl8xxxu_rxdesc16) / sizeof(u32)); i++) |
6420 | _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); |
6421 | |
6422 | /* |
6423 | * Only read pkt_cnt from the header if we're parsing the |
6424 | * first packet |
6425 | */ |
6426 | if (!pkt_cnt) |
6427 | pkt_cnt = rx_desc->pkt_cnt; |
6428 | pkt_len = rx_desc->pktlen; |
6429 | |
6430 | drvinfo_sz = rx_desc->drvinfo_sz * 8; |
6431 | desc_shift = rx_desc->shift; |
6432 | pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift + |
6433 | sizeof(struct rtl8xxxu_rxdesc16), 128); |
6434 | |
6435 | /* |
6436 | * Only clone the skb if there's enough data at the end to |
6437 | * at least cover the rx descriptor |
6438 | */ |
6439 | if (pkt_cnt > 1 && |
6440 | urb_len >= (pkt_offset + sizeof(struct rtl8xxxu_rxdesc16))) |
6441 | next_skb = skb_clone(skb, GFP_ATOMIC); |
6442 | |
6443 | rx_status = IEEE80211_SKB_RXCB(skb); |
6444 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
6445 | |
6446 | skb_pull(skb, len: sizeof(struct rtl8xxxu_rxdesc16)); |
6447 | |
6448 | if (rx_desc->rpt_sel) { |
6449 | skb_queue_tail(list: &priv->c2hcmd_queue, newsk: skb); |
6450 | schedule_work(work: &priv->c2hcmd_work); |
6451 | } else { |
6452 | struct ieee80211_hdr *hdr; |
6453 | |
6454 | phy_stats = (struct rtl8723au_phy_stats *)skb->data; |
6455 | |
6456 | skb_pull(skb, len: drvinfo_sz + desc_shift); |
6457 | |
6458 | skb_trim(skb, len: pkt_len); |
6459 | |
6460 | hdr = (struct ieee80211_hdr *)skb->data; |
6461 | if (rx_desc->phy_stats) { |
6462 | priv->fops->parse_phystats( |
6463 | priv, rx_status, phy_stats, |
6464 | rx_desc->rxmcs, |
6465 | hdr, |
6466 | rx_desc->crc32 || rx_desc->icverr); |
6467 | if (!rx_desc->crc32 && !rx_desc->icverr) |
6468 | rtl8xxxu_rx_update_rssi(priv, |
6469 | rx_status, |
6470 | hdr); |
6471 | } |
6472 | |
6473 | rx_status->mactime = rx_desc->tsfl; |
6474 | rx_status->flag |= RX_FLAG_MACTIME_START; |
6475 | |
6476 | if (!rx_desc->swdec) |
6477 | rx_status->flag |= RX_FLAG_DECRYPTED; |
6478 | if (rx_desc->crc32) |
6479 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
6480 | if (rx_desc->bw) |
6481 | rx_status->bw = RATE_INFO_BW_40; |
6482 | |
6483 | if (rx_desc->rxht) { |
6484 | rx_status->encoding = RX_ENC_HT; |
6485 | rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; |
6486 | } else { |
6487 | rx_status->rate_idx = rx_desc->rxmcs; |
6488 | } |
6489 | |
6490 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
6491 | rx_status->band = hw->conf.chandef.chan->band; |
6492 | |
6493 | ieee80211_rx_irqsafe(hw, skb); |
6494 | } |
6495 | |
6496 | skb = next_skb; |
6497 | if (skb) |
6498 | skb_pull(skb: next_skb, len: pkt_offset); |
6499 | |
6500 | pkt_cnt--; |
6501 | urb_len -= pkt_offset; |
6502 | next_skb = NULL; |
6503 | } while (skb && pkt_cnt > 0 && |
6504 | urb_len >= sizeof(struct rtl8xxxu_rxdesc16)); |
6505 | |
6506 | return RX_TYPE_DATA_PKT; |
6507 | } |
6508 | |
6509 | int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb) |
6510 | { |
6511 | struct ieee80211_hw *hw = priv->hw; |
6512 | struct ieee80211_rx_status *rx_status; |
6513 | struct rtl8xxxu_rxdesc24 *rx_desc; |
6514 | struct rtl8723au_phy_stats *phy_stats; |
6515 | struct sk_buff *next_skb = NULL; |
6516 | __le32 *_rx_desc_le; |
6517 | u32 *_rx_desc; |
6518 | int drvinfo_sz, desc_shift; |
6519 | int i, pkt_len, urb_len, pkt_offset; |
6520 | |
6521 | urb_len = skb->len; |
6522 | |
6523 | if (urb_len < sizeof(struct rtl8xxxu_rxdesc24)) { |
6524 | kfree_skb(skb); |
6525 | return RX_TYPE_ERROR; |
6526 | } |
6527 | |
6528 | do { |
6529 | rx_desc = (struct rtl8xxxu_rxdesc24 *)skb->data; |
6530 | _rx_desc_le = (__le32 *)skb->data; |
6531 | _rx_desc = (u32 *)skb->data; |
6532 | |
6533 | for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++) |
6534 | _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); |
6535 | |
6536 | pkt_len = rx_desc->pktlen; |
6537 | |
6538 | drvinfo_sz = rx_desc->drvinfo_sz * 8; |
6539 | desc_shift = rx_desc->shift; |
6540 | pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift + |
6541 | sizeof(struct rtl8xxxu_rxdesc24), 8); |
6542 | |
6543 | /* |
6544 | * Only clone the skb if there's enough data at the end to |
6545 | * at least cover the rx descriptor |
6546 | */ |
6547 | if (urb_len >= (pkt_offset + sizeof(struct rtl8xxxu_rxdesc24))) |
6548 | next_skb = skb_clone(skb, GFP_ATOMIC); |
6549 | |
6550 | rx_status = IEEE80211_SKB_RXCB(skb); |
6551 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
6552 | |
6553 | skb_pull(skb, len: sizeof(struct rtl8xxxu_rxdesc24)); |
6554 | |
6555 | phy_stats = (struct rtl8723au_phy_stats *)skb->data; |
6556 | |
6557 | skb_pull(skb, len: drvinfo_sz + desc_shift); |
6558 | |
6559 | skb_trim(skb, len: pkt_len); |
6560 | |
6561 | if (rx_desc->rpt_sel) { |
6562 | struct device *dev = &priv->udev->dev; |
6563 | dev_dbg(dev, "%s: C2H packet\n" , __func__); |
6564 | rtl8723bu_handle_c2h(priv, skb); |
6565 | } else { |
6566 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
6567 | |
6568 | if (rx_desc->phy_stats) { |
6569 | priv->fops->parse_phystats(priv, rx_status, phy_stats, |
6570 | rx_desc->rxmcs, hdr, |
6571 | rx_desc->crc32 || rx_desc->icverr); |
6572 | if (!rx_desc->crc32 && !rx_desc->icverr) |
6573 | rtl8xxxu_rx_update_rssi(priv, |
6574 | rx_status, |
6575 | hdr); |
6576 | } |
6577 | |
6578 | rx_status->mactime = rx_desc->tsfl; |
6579 | rx_status->flag |= RX_FLAG_MACTIME_START; |
6580 | |
6581 | if (!rx_desc->swdec) |
6582 | rx_status->flag |= RX_FLAG_DECRYPTED; |
6583 | if (rx_desc->crc32) |
6584 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
6585 | if (rx_desc->bw) |
6586 | rx_status->bw = RATE_INFO_BW_40; |
6587 | |
6588 | if (rx_desc->rxmcs >= DESC_RATE_MCS0) { |
6589 | rx_status->encoding = RX_ENC_HT; |
6590 | rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; |
6591 | } else { |
6592 | rx_status->rate_idx = rx_desc->rxmcs; |
6593 | } |
6594 | |
6595 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
6596 | rx_status->band = hw->conf.chandef.chan->band; |
6597 | |
6598 | ieee80211_rx_irqsafe(hw, skb); |
6599 | } |
6600 | |
6601 | skb = next_skb; |
6602 | if (skb) |
6603 | skb_pull(skb: next_skb, len: pkt_offset); |
6604 | |
6605 | urb_len -= pkt_offset; |
6606 | next_skb = NULL; |
6607 | } while (skb && urb_len >= sizeof(struct rtl8xxxu_rxdesc24)); |
6608 | |
6609 | return RX_TYPE_DATA_PKT; |
6610 | } |
6611 | |
6612 | static void rtl8xxxu_rx_complete(struct urb *urb) |
6613 | { |
6614 | struct rtl8xxxu_rx_urb *rx_urb = |
6615 | container_of(urb, struct rtl8xxxu_rx_urb, urb); |
6616 | struct ieee80211_hw *hw = rx_urb->hw; |
6617 | struct rtl8xxxu_priv *priv = hw->priv; |
6618 | struct sk_buff *skb = (struct sk_buff *)urb->context; |
6619 | struct device *dev = &priv->udev->dev; |
6620 | |
6621 | skb_put(skb, len: urb->actual_length); |
6622 | |
6623 | if (urb->status == 0) { |
6624 | priv->fops->parse_rx_desc(priv, skb); |
6625 | |
6626 | skb = NULL; |
6627 | rx_urb->urb.context = NULL; |
6628 | rtl8xxxu_queue_rx_urb(priv, rx_urb); |
6629 | } else { |
6630 | dev_dbg(dev, "%s: status %i\n" , __func__, urb->status); |
6631 | goto cleanup; |
6632 | } |
6633 | return; |
6634 | |
6635 | cleanup: |
6636 | usb_free_urb(urb); |
6637 | dev_kfree_skb(skb); |
6638 | } |
6639 | |
6640 | static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, |
6641 | struct rtl8xxxu_rx_urb *rx_urb) |
6642 | { |
6643 | struct rtl8xxxu_fileops *fops = priv->fops; |
6644 | struct sk_buff *skb; |
6645 | int skb_size; |
6646 | int ret, rx_desc_sz; |
6647 | |
6648 | rx_desc_sz = fops->rx_desc_size; |
6649 | |
6650 | if (priv->rx_buf_aggregation && fops->rx_agg_buf_size) { |
6651 | skb_size = fops->rx_agg_buf_size; |
6652 | skb_size += (rx_desc_sz + sizeof(struct rtl8723au_phy_stats)); |
6653 | } else { |
6654 | skb_size = IEEE80211_MAX_FRAME_LEN; |
6655 | } |
6656 | |
6657 | skb = __netdev_alloc_skb(NULL, length: skb_size, GFP_KERNEL); |
6658 | if (!skb) |
6659 | return -ENOMEM; |
6660 | |
6661 | memset(skb->data, 0, rx_desc_sz); |
6662 | usb_fill_bulk_urb(urb: &rx_urb->urb, dev: priv->udev, pipe: priv->pipe_in, transfer_buffer: skb->data, |
6663 | buffer_length: skb_size, complete_fn: rtl8xxxu_rx_complete, context: skb); |
6664 | usb_anchor_urb(urb: &rx_urb->urb, anchor: &priv->rx_anchor); |
6665 | ret = usb_submit_urb(urb: &rx_urb->urb, GFP_ATOMIC); |
6666 | if (ret) |
6667 | usb_unanchor_urb(urb: &rx_urb->urb); |
6668 | return ret; |
6669 | } |
6670 | |
6671 | static void rtl8xxxu_int_complete(struct urb *urb) |
6672 | { |
6673 | struct rtl8xxxu_priv *priv = (struct rtl8xxxu_priv *)urb->context; |
6674 | struct device *dev = &priv->udev->dev; |
6675 | int ret; |
6676 | |
6677 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_INTERRUPT) |
6678 | dev_dbg(dev, "%s: status %i\n" , __func__, urb->status); |
6679 | if (urb->status == 0) { |
6680 | usb_anchor_urb(urb, anchor: &priv->int_anchor); |
6681 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
6682 | if (ret) |
6683 | usb_unanchor_urb(urb); |
6684 | } else { |
6685 | dev_dbg(dev, "%s: Error %i\n" , __func__, urb->status); |
6686 | } |
6687 | } |
6688 | |
6689 | |
6690 | static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw) |
6691 | { |
6692 | struct rtl8xxxu_priv *priv = hw->priv; |
6693 | struct urb *urb; |
6694 | u32 val32; |
6695 | int ret; |
6696 | |
6697 | urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
6698 | if (!urb) |
6699 | return -ENOMEM; |
6700 | |
6701 | usb_fill_int_urb(urb, dev: priv->udev, pipe: priv->pipe_interrupt, |
6702 | transfer_buffer: priv->int_buf, USB_INTR_CONTENT_LENGTH, |
6703 | complete_fn: rtl8xxxu_int_complete, context: priv, interval: 1); |
6704 | usb_anchor_urb(urb, anchor: &priv->int_anchor); |
6705 | ret = usb_submit_urb(urb, GFP_KERNEL); |
6706 | if (ret) { |
6707 | usb_unanchor_urb(urb); |
6708 | goto error; |
6709 | } |
6710 | |
6711 | val32 = rtl8xxxu_read32(priv, REG_USB_HIMR); |
6712 | val32 |= USB_HIMR_CPWM; |
6713 | rtl8xxxu_write32(priv, REG_USB_HIMR, val: val32); |
6714 | |
6715 | error: |
6716 | usb_free_urb(urb); |
6717 | return ret; |
6718 | } |
6719 | |
6720 | static void rtl8xxxu_switch_ports(struct rtl8xxxu_priv *priv) |
6721 | { |
6722 | u8 macid[ETH_ALEN], bssid[ETH_ALEN], macid_1[ETH_ALEN], bssid_1[ETH_ALEN]; |
6723 | u8 msr, bcn_ctrl, bcn_ctrl_1, atimwnd[2], atimwnd_1[2]; |
6724 | struct rtl8xxxu_vif *rtlvif; |
6725 | struct ieee80211_vif *vif; |
6726 | u8 tsftr[8], tsftr_1[8]; |
6727 | int i; |
6728 | |
6729 | msr = rtl8xxxu_read8(priv, REG_MSR); |
6730 | bcn_ctrl = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
6731 | bcn_ctrl_1 = rtl8xxxu_read8(priv, REG_BEACON_CTRL_1); |
6732 | |
6733 | for (i = 0; i < ARRAY_SIZE(atimwnd); i++) |
6734 | atimwnd[i] = rtl8xxxu_read8(priv, REG_ATIMWND + i); |
6735 | for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++) |
6736 | atimwnd_1[i] = rtl8xxxu_read8(priv, REG_ATIMWND_1 + i); |
6737 | |
6738 | for (i = 0; i < ARRAY_SIZE(tsftr); i++) |
6739 | tsftr[i] = rtl8xxxu_read8(priv, REG_TSFTR + i); |
6740 | for (i = 0; i < ARRAY_SIZE(tsftr); i++) |
6741 | tsftr_1[i] = rtl8xxxu_read8(priv, REG_TSFTR1 + i); |
6742 | |
6743 | for (i = 0; i < ARRAY_SIZE(macid); i++) |
6744 | macid[i] = rtl8xxxu_read8(priv, REG_MACID + i); |
6745 | |
6746 | for (i = 0; i < ARRAY_SIZE(bssid); i++) |
6747 | bssid[i] = rtl8xxxu_read8(priv, REG_BSSID + i); |
6748 | |
6749 | for (i = 0; i < ARRAY_SIZE(macid_1); i++) |
6750 | macid_1[i] = rtl8xxxu_read8(priv, REG_MACID1 + i); |
6751 | |
6752 | for (i = 0; i < ARRAY_SIZE(bssid_1); i++) |
6753 | bssid_1[i] = rtl8xxxu_read8(priv, REG_BSSID1 + i); |
6754 | |
6755 | /* disable bcn function, disable update TSF */ |
6756 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: (bcn_ctrl & |
6757 | (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE); |
6758 | rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, val: (bcn_ctrl_1 & |
6759 | (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE); |
6760 | |
6761 | /* switch msr */ |
6762 | msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2); |
6763 | rtl8xxxu_write8(priv, REG_MSR, val: msr); |
6764 | |
6765 | /* write port0 */ |
6766 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: bcn_ctrl_1 & ~BEACON_FUNCTION_ENABLE); |
6767 | for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++) |
6768 | rtl8xxxu_write8(priv, REG_ATIMWND + i, val: atimwnd_1[i]); |
6769 | for (i = 0; i < ARRAY_SIZE(tsftr_1); i++) |
6770 | rtl8xxxu_write8(priv, REG_TSFTR + i, val: tsftr_1[i]); |
6771 | for (i = 0; i < ARRAY_SIZE(macid_1); i++) |
6772 | rtl8xxxu_write8(priv, REG_MACID + i, val: macid_1[i]); |
6773 | for (i = 0; i < ARRAY_SIZE(bssid_1); i++) |
6774 | rtl8xxxu_write8(priv, REG_BSSID + i, val: bssid_1[i]); |
6775 | |
6776 | /* write port1 */ |
6777 | rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, val: bcn_ctrl & ~BEACON_FUNCTION_ENABLE); |
6778 | for (i = 0; i < ARRAY_SIZE(atimwnd); i++) |
6779 | rtl8xxxu_write8(priv, REG_ATIMWND_1 + i, val: atimwnd[i]); |
6780 | for (i = 0; i < ARRAY_SIZE(tsftr); i++) |
6781 | rtl8xxxu_write8(priv, REG_TSFTR1 + i, val: tsftr[i]); |
6782 | for (i = 0; i < ARRAY_SIZE(macid); i++) |
6783 | rtl8xxxu_write8(priv, REG_MACID1 + i, val: macid[i]); |
6784 | for (i = 0; i < ARRAY_SIZE(bssid); i++) |
6785 | rtl8xxxu_write8(priv, REG_BSSID1 + i, val: bssid[i]); |
6786 | |
6787 | /* write bcn ctl */ |
6788 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: bcn_ctrl_1); |
6789 | rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, val: bcn_ctrl); |
6790 | |
6791 | vif = priv->vifs[0]; |
6792 | priv->vifs[0] = priv->vifs[1]; |
6793 | priv->vifs[1] = vif; |
6794 | |
6795 | /* priv->vifs[0] is NULL here, based on how this function is currently |
6796 | * called from rtl8xxxu_add_interface(). |
6797 | * When this function will be used in the future for a different |
6798 | * scenario, please check whether vifs[0] or vifs[1] can be NULL and if |
6799 | * necessary add code to set port_num = 1. |
6800 | */ |
6801 | rtlvif = (struct rtl8xxxu_vif *)priv->vifs[1]->drv_priv; |
6802 | rtlvif->port_num = 1; |
6803 | } |
6804 | |
6805 | static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, |
6806 | struct ieee80211_vif *vif) |
6807 | { |
6808 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
6809 | struct rtl8xxxu_priv *priv = hw->priv; |
6810 | int port_num; |
6811 | u8 val8; |
6812 | |
6813 | if (!priv->vifs[0]) |
6814 | port_num = 0; |
6815 | else if (!priv->vifs[1]) |
6816 | port_num = 1; |
6817 | else |
6818 | return -EOPNOTSUPP; |
6819 | |
6820 | switch (vif->type) { |
6821 | case NL80211_IFTYPE_STATION: |
6822 | if (port_num == 0) { |
6823 | rtl8xxxu_stop_tx_beacon(priv); |
6824 | |
6825 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
6826 | val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | |
6827 | BEACON_DISABLE_TSF_UPDATE; |
6828 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val: val8); |
6829 | } |
6830 | break; |
6831 | case NL80211_IFTYPE_AP: |
6832 | if (port_num == 1) { |
6833 | rtl8xxxu_switch_ports(priv); |
6834 | port_num = 0; |
6835 | } |
6836 | |
6837 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, |
6838 | BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID); |
6839 | rtl8xxxu_write8(priv, REG_ATIMWND, val: 0x0c); /* 12ms */ |
6840 | rtl8xxxu_write16(priv, REG_TSFTR_SYN_OFFSET, val: 0x7fff); /* ~32ms */ |
6841 | rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, DUAL_TSF_RESET_TSF0); |
6842 | |
6843 | /* enable BCN0 function */ |
6844 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, |
6845 | BEACON_DISABLE_TSF_UPDATE | |
6846 | BEACON_FUNCTION_ENABLE | BEACON_CTRL_MBSSID | |
6847 | BEACON_CTRL_TX_BEACON_RPT); |
6848 | |
6849 | /* select BCN on port 0 */ |
6850 | val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK); |
6851 | val8 &= ~BIT_BCN_PORT_SEL; |
6852 | rtl8xxxu_write8(priv, REG_CCK_CHECK, val: val8); |
6853 | break; |
6854 | default: |
6855 | return -EOPNOTSUPP; |
6856 | } |
6857 | |
6858 | priv->vifs[port_num] = vif; |
6859 | rtlvif->port_num = port_num; |
6860 | rtlvif->hw_key_idx = 0xff; |
6861 | |
6862 | rtl8xxxu_set_linktype(priv, linktype: vif->type, port_num); |
6863 | ether_addr_copy(dst: priv->mac_addr, src: vif->addr); |
6864 | rtl8xxxu_set_mac(priv, port_num); |
6865 | |
6866 | return 0; |
6867 | } |
6868 | |
6869 | static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw, |
6870 | struct ieee80211_vif *vif) |
6871 | { |
6872 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
6873 | struct rtl8xxxu_priv *priv = hw->priv; |
6874 | |
6875 | dev_dbg(&priv->udev->dev, "%s\n" , __func__); |
6876 | |
6877 | priv->vifs[rtlvif->port_num] = NULL; |
6878 | } |
6879 | |
6880 | static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) |
6881 | { |
6882 | struct rtl8xxxu_priv *priv = hw->priv; |
6883 | struct device *dev = &priv->udev->dev; |
6884 | int ret = 0, channel; |
6885 | bool ht40; |
6886 | |
6887 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) |
6888 | dev_info(dev, |
6889 | "%s: channel: %i (changed %08x chandef.width %02x)\n" , |
6890 | __func__, hw->conf.chandef.chan->hw_value, |
6891 | changed, hw->conf.chandef.width); |
6892 | |
6893 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
6894 | switch (hw->conf.chandef.width) { |
6895 | case NL80211_CHAN_WIDTH_20_NOHT: |
6896 | case NL80211_CHAN_WIDTH_20: |
6897 | ht40 = false; |
6898 | break; |
6899 | case NL80211_CHAN_WIDTH_40: |
6900 | ht40 = true; |
6901 | break; |
6902 | default: |
6903 | ret = -ENOTSUPP; |
6904 | goto exit; |
6905 | } |
6906 | |
6907 | channel = hw->conf.chandef.chan->hw_value; |
6908 | |
6909 | priv->fops->set_tx_power(priv, channel, ht40); |
6910 | |
6911 | priv->fops->config_channel(hw); |
6912 | } |
6913 | |
6914 | exit: |
6915 | return ret; |
6916 | } |
6917 | |
6918 | static int rtl8xxxu_conf_tx(struct ieee80211_hw *hw, |
6919 | struct ieee80211_vif *vif, |
6920 | unsigned int link_id, u16 queue, |
6921 | const struct ieee80211_tx_queue_params *param) |
6922 | { |
6923 | struct rtl8xxxu_priv *priv = hw->priv; |
6924 | struct device *dev = &priv->udev->dev; |
6925 | u32 val32; |
6926 | u8 aifs, acm_ctrl, acm_bit; |
6927 | |
6928 | aifs = param->aifs; |
6929 | |
6930 | val32 = aifs | |
6931 | fls(x: param->cw_min) << EDCA_PARAM_ECW_MIN_SHIFT | |
6932 | fls(x: param->cw_max) << EDCA_PARAM_ECW_MAX_SHIFT | |
6933 | (u32)param->txop << EDCA_PARAM_TXOP_SHIFT; |
6934 | |
6935 | acm_ctrl = rtl8xxxu_read8(priv, REG_ACM_HW_CTRL); |
6936 | dev_dbg(dev, |
6937 | "%s: IEEE80211 queue %02x val %08x, acm %i, acm_ctrl %02x\n" , |
6938 | __func__, queue, val32, param->acm, acm_ctrl); |
6939 | |
6940 | switch (queue) { |
6941 | case IEEE80211_AC_VO: |
6942 | acm_bit = ACM_HW_CTRL_VO; |
6943 | rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, val: val32); |
6944 | break; |
6945 | case IEEE80211_AC_VI: |
6946 | acm_bit = ACM_HW_CTRL_VI; |
6947 | rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, val: val32); |
6948 | break; |
6949 | case IEEE80211_AC_BE: |
6950 | acm_bit = ACM_HW_CTRL_BE; |
6951 | rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, val: val32); |
6952 | break; |
6953 | case IEEE80211_AC_BK: |
6954 | acm_bit = ACM_HW_CTRL_BK; |
6955 | rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, val: val32); |
6956 | break; |
6957 | default: |
6958 | acm_bit = 0; |
6959 | break; |
6960 | } |
6961 | |
6962 | if (param->acm) |
6963 | acm_ctrl |= acm_bit; |
6964 | else |
6965 | acm_ctrl &= ~acm_bit; |
6966 | rtl8xxxu_write8(priv, REG_ACM_HW_CTRL, val: acm_ctrl); |
6967 | |
6968 | return 0; |
6969 | } |
6970 | |
6971 | static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, |
6972 | unsigned int changed_flags, |
6973 | unsigned int *total_flags, u64 multicast) |
6974 | { |
6975 | struct rtl8xxxu_priv *priv = hw->priv; |
6976 | u32 rcr = priv->regrcr; |
6977 | |
6978 | dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n" , |
6979 | __func__, changed_flags, *total_flags); |
6980 | |
6981 | /* |
6982 | * FIF_ALLMULTI ignored as all multicast frames are accepted (REG_MAR) |
6983 | */ |
6984 | |
6985 | if (*total_flags & FIF_FCSFAIL) |
6986 | rcr |= RCR_ACCEPT_CRC32; |
6987 | else |
6988 | rcr &= ~RCR_ACCEPT_CRC32; |
6989 | |
6990 | /* |
6991 | * FIF_PLCPFAIL not supported? |
6992 | */ |
6993 | |
6994 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) |
6995 | rcr &= ~(RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH); |
6996 | else |
6997 | rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH; |
6998 | |
6999 | if (priv->vifs[0] && priv->vifs[0]->type == NL80211_IFTYPE_AP) |
7000 | rcr &= ~(RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON); |
7001 | |
7002 | if (*total_flags & FIF_CONTROL) |
7003 | rcr |= RCR_ACCEPT_CTRL_FRAME; |
7004 | else |
7005 | rcr &= ~RCR_ACCEPT_CTRL_FRAME; |
7006 | |
7007 | if (*total_flags & FIF_OTHER_BSS) |
7008 | rcr |= RCR_ACCEPT_AP; |
7009 | else |
7010 | rcr &= ~RCR_ACCEPT_AP; |
7011 | |
7012 | if (*total_flags & FIF_PSPOLL) |
7013 | rcr |= RCR_ACCEPT_PM; |
7014 | else |
7015 | rcr &= ~RCR_ACCEPT_PM; |
7016 | |
7017 | /* |
7018 | * FIF_PROBE_REQ ignored as probe requests always seem to be accepted |
7019 | */ |
7020 | |
7021 | rtl8xxxu_write32(priv, REG_RCR, val: rcr); |
7022 | priv->regrcr = rcr; |
7023 | |
7024 | *total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC | |
7025 | FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL | |
7026 | FIF_PROBE_REQ); |
7027 | } |
7028 | |
7029 | static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) |
7030 | { |
7031 | if (rts > 2347 && rts != (u32)-1) |
7032 | return -EINVAL; |
7033 | |
7034 | return 0; |
7035 | } |
7036 | |
7037 | static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw) |
7038 | { |
7039 | struct rtl8xxxu_priv *priv = hw->priv; |
7040 | |
7041 | return find_first_zero_bit(addr: priv->cam_map, size: priv->fops->max_sec_cam_num); |
7042 | } |
7043 | |
7044 | static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
7045 | struct ieee80211_vif *vif, |
7046 | struct ieee80211_sta *sta, |
7047 | struct ieee80211_key_conf *key) |
7048 | { |
7049 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
7050 | struct rtl8xxxu_priv *priv = hw->priv; |
7051 | struct device *dev = &priv->udev->dev; |
7052 | u8 mac_addr[ETH_ALEN]; |
7053 | u8 val8; |
7054 | u16 val16; |
7055 | u32 val32; |
7056 | int retval = -EOPNOTSUPP; |
7057 | |
7058 | dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n" , |
7059 | __func__, cmd, key->cipher, key->keyidx); |
7060 | |
7061 | if (key->keyidx > 3) |
7062 | return -EOPNOTSUPP; |
7063 | |
7064 | switch (key->cipher) { |
7065 | case WLAN_CIPHER_SUITE_WEP40: |
7066 | case WLAN_CIPHER_SUITE_WEP104: |
7067 | |
7068 | break; |
7069 | case WLAN_CIPHER_SUITE_CCMP: |
7070 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
7071 | break; |
7072 | case WLAN_CIPHER_SUITE_TKIP: |
7073 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
7074 | break; |
7075 | default: |
7076 | return -EOPNOTSUPP; |
7077 | } |
7078 | |
7079 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
7080 | dev_dbg(dev, "%s: pairwise key\n" , __func__); |
7081 | ether_addr_copy(dst: mac_addr, src: sta->addr); |
7082 | } else { |
7083 | dev_dbg(dev, "%s: group key\n" , __func__); |
7084 | ether_addr_copy(dst: mac_addr, src: vif->bss_conf.bssid); |
7085 | } |
7086 | |
7087 | val16 = rtl8xxxu_read16(priv, REG_CR); |
7088 | val16 |= CR_SECURITY_ENABLE; |
7089 | rtl8xxxu_write16(priv, REG_CR, val: val16); |
7090 | |
7091 | val8 = SEC_CFG_TX_SEC_ENABLE | SEC_CFG_TXBC_USE_DEFKEY | |
7092 | SEC_CFG_RX_SEC_ENABLE | SEC_CFG_RXBC_USE_DEFKEY; |
7093 | val8 |= SEC_CFG_TX_USE_DEFKEY | SEC_CFG_RX_USE_DEFKEY; |
7094 | rtl8xxxu_write8(priv, REG_SECURITY_CFG, val: val8); |
7095 | |
7096 | switch (cmd) { |
7097 | case SET_KEY: |
7098 | |
7099 | retval = rtl8xxxu_get_free_sec_cam(hw); |
7100 | if (retval < 0) |
7101 | return -EOPNOTSUPP; |
7102 | |
7103 | key->hw_key_idx = retval; |
7104 | |
7105 | if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
7106 | rtlvif->hw_key_idx = key->hw_key_idx; |
7107 | |
7108 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
7109 | rtl8xxxu_cam_write(priv, key, mac: mac_addr); |
7110 | set_bit(nr: key->hw_key_idx, addr: priv->cam_map); |
7111 | retval = 0; |
7112 | break; |
7113 | case DISABLE_KEY: |
7114 | rtl8xxxu_write32(priv, REG_CAM_WRITE, val: 0x00000000); |
7115 | val32 = CAM_CMD_POLLING | CAM_CMD_WRITE | |
7116 | key->hw_key_idx << CAM_CMD_KEY_SHIFT; |
7117 | rtl8xxxu_write32(priv, REG_CAM_CMD, val: val32); |
7118 | rtlvif->hw_key_idx = 0xff; |
7119 | clear_bit(nr: key->hw_key_idx, addr: priv->cam_map); |
7120 | retval = 0; |
7121 | break; |
7122 | default: |
7123 | dev_warn(dev, "%s: Unsupported command %02x\n" , __func__, cmd); |
7124 | } |
7125 | |
7126 | return retval; |
7127 | } |
7128 | |
7129 | static int |
7130 | rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
7131 | struct ieee80211_ampdu_params *params) |
7132 | { |
7133 | struct rtl8xxxu_priv *priv = hw->priv; |
7134 | struct device *dev = &priv->udev->dev; |
7135 | u8 ampdu_factor, ampdu_density; |
7136 | struct ieee80211_sta *sta = params->sta; |
7137 | u16 tid = params->tid; |
7138 | enum ieee80211_ampdu_mlme_action action = params->action; |
7139 | |
7140 | switch (action) { |
7141 | case IEEE80211_AMPDU_TX_START: |
7142 | dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_START\n" , __func__); |
7143 | ampdu_factor = sta->deflink.ht_cap.ampdu_factor; |
7144 | ampdu_density = sta->deflink.ht_cap.ampdu_density; |
7145 | rtl8xxxu_set_ampdu_factor(priv, ampdu_factor); |
7146 | rtl8xxxu_set_ampdu_min_space(priv, density: ampdu_density); |
7147 | dev_dbg(dev, |
7148 | "Changed HT: ampdu_factor %02x, ampdu_density %02x\n" , |
7149 | ampdu_factor, ampdu_density); |
7150 | return IEEE80211_AMPDU_TX_START_IMMEDIATE; |
7151 | case IEEE80211_AMPDU_TX_STOP_CONT: |
7152 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
7153 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
7154 | dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP\n" , __func__); |
7155 | rtl8xxxu_set_ampdu_factor(priv, ampdu_factor: 0); |
7156 | rtl8xxxu_set_ampdu_min_space(priv, density: 0); |
7157 | clear_bit(nr: tid, addr: priv->tx_aggr_started); |
7158 | clear_bit(nr: tid, addr: priv->tid_tx_operational); |
7159 | ieee80211_stop_tx_ba_cb_irqsafe(vif, ra: sta->addr, tid); |
7160 | break; |
7161 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
7162 | dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_OPERATIONAL\n" , __func__); |
7163 | set_bit(nr: tid, addr: priv->tid_tx_operational); |
7164 | break; |
7165 | case IEEE80211_AMPDU_RX_START: |
7166 | dev_dbg(dev, "%s: IEEE80211_AMPDU_RX_START\n" , __func__); |
7167 | break; |
7168 | case IEEE80211_AMPDU_RX_STOP: |
7169 | dev_dbg(dev, "%s: IEEE80211_AMPDU_RX_STOP\n" , __func__); |
7170 | break; |
7171 | default: |
7172 | break; |
7173 | } |
7174 | return 0; |
7175 | } |
7176 | |
7177 | static void |
7178 | rtl8xxxu_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
7179 | struct ieee80211_sta *sta, struct station_info *sinfo) |
7180 | { |
7181 | struct rtl8xxxu_priv *priv = hw->priv; |
7182 | |
7183 | sinfo->txrate = priv->ra_report.txrate; |
7184 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
7185 | } |
7186 | |
7187 | static u8 rtl8xxxu_signal_to_snr(int signal) |
7188 | { |
7189 | if (signal < RTL8XXXU_NOISE_FLOOR_MIN) |
7190 | signal = RTL8XXXU_NOISE_FLOOR_MIN; |
7191 | else if (signal > 0) |
7192 | signal = 0; |
7193 | return (u8)(signal - RTL8XXXU_NOISE_FLOOR_MIN); |
7194 | } |
7195 | |
7196 | static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, |
7197 | int signal, struct ieee80211_sta *sta, |
7198 | bool force) |
7199 | { |
7200 | struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
7201 | struct ieee80211_hw *hw = priv->hw; |
7202 | u16 wireless_mode; |
7203 | u8 , ratr_idx; |
7204 | u8 txbw_40mhz; |
7205 | u8 snr, snr_thresh_high, snr_thresh_low; |
7206 | u8 go_up_gap = 5; |
7207 | u8 macid = rtl8xxxu_get_macid(priv, sta); |
7208 | |
7209 | rssi_level = sta_info->rssi_level; |
7210 | snr = rtl8xxxu_signal_to_snr(signal); |
7211 | snr_thresh_high = RTL8XXXU_SNR_THRESH_HIGH; |
7212 | snr_thresh_low = RTL8XXXU_SNR_THRESH_LOW; |
7213 | txbw_40mhz = (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) ? 1 : 0; |
7214 | |
7215 | switch (rssi_level) { |
7216 | case RTL8XXXU_RATR_STA_MID: |
7217 | snr_thresh_high += go_up_gap; |
7218 | break; |
7219 | case RTL8XXXU_RATR_STA_LOW: |
7220 | snr_thresh_high += go_up_gap; |
7221 | snr_thresh_low += go_up_gap; |
7222 | break; |
7223 | default: |
7224 | break; |
7225 | } |
7226 | |
7227 | if (snr > snr_thresh_high) |
7228 | rssi_level = RTL8XXXU_RATR_STA_HIGH; |
7229 | else if (snr > snr_thresh_low) |
7230 | rssi_level = RTL8XXXU_RATR_STA_MID; |
7231 | else |
7232 | rssi_level = RTL8XXXU_RATR_STA_LOW; |
7233 | |
7234 | if (rssi_level != sta_info->rssi_level || force) { |
7235 | int sgi = 0; |
7236 | u32 rate_bitmap = 0; |
7237 | |
7238 | rate_bitmap = (sta->deflink.supp_rates[0] & 0xfff) | |
7239 | (sta->deflink.ht_cap.mcs.rx_mask[0] << 12) | |
7240 | (sta->deflink.ht_cap.mcs.rx_mask[1] << 20); |
7241 | if (sta->deflink.ht_cap.cap & |
7242 | (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) |
7243 | sgi = 1; |
7244 | |
7245 | wireless_mode = rtl8xxxu_wireless_mode(hw, sta); |
7246 | switch (wireless_mode) { |
7247 | case WIRELESS_MODE_B: |
7248 | ratr_idx = RATEID_IDX_B; |
7249 | if (rate_bitmap & 0x0000000c) |
7250 | rate_bitmap &= 0x0000000d; |
7251 | else |
7252 | rate_bitmap &= 0x0000000f; |
7253 | break; |
7254 | case WIRELESS_MODE_A: |
7255 | case WIRELESS_MODE_G: |
7256 | ratr_idx = RATEID_IDX_G; |
7257 | if (rssi_level == RTL8XXXU_RATR_STA_HIGH) |
7258 | rate_bitmap &= 0x00000f00; |
7259 | else |
7260 | rate_bitmap &= 0x00000ff0; |
7261 | break; |
7262 | case (WIRELESS_MODE_B | WIRELESS_MODE_G): |
7263 | ratr_idx = RATEID_IDX_BG; |
7264 | if (rssi_level == RTL8XXXU_RATR_STA_HIGH) |
7265 | rate_bitmap &= 0x00000f00; |
7266 | else if (rssi_level == RTL8XXXU_RATR_STA_MID) |
7267 | rate_bitmap &= 0x00000ff0; |
7268 | else |
7269 | rate_bitmap &= 0x00000ff5; |
7270 | break; |
7271 | case WIRELESS_MODE_N_24G: |
7272 | case WIRELESS_MODE_N_5G: |
7273 | case (WIRELESS_MODE_G | WIRELESS_MODE_N_24G): |
7274 | case (WIRELESS_MODE_A | WIRELESS_MODE_N_5G): |
7275 | if (priv->tx_paths == 2 && priv->rx_paths == 2) |
7276 | ratr_idx = RATEID_IDX_GN_N2SS; |
7277 | else |
7278 | ratr_idx = RATEID_IDX_GN_N1SS; |
7279 | break; |
7280 | case (WIRELESS_MODE_B | WIRELESS_MODE_G | WIRELESS_MODE_N_24G): |
7281 | case (WIRELESS_MODE_B | WIRELESS_MODE_N_24G): |
7282 | if (txbw_40mhz) { |
7283 | if (priv->tx_paths == 2 && priv->rx_paths == 2) |
7284 | ratr_idx = RATEID_IDX_BGN_40M_2SS; |
7285 | else |
7286 | ratr_idx = RATEID_IDX_BGN_40M_1SS; |
7287 | } else { |
7288 | if (priv->tx_paths == 2 && priv->rx_paths == 2) |
7289 | ratr_idx = RATEID_IDX_BGN_20M_2SS_BN; |
7290 | else |
7291 | ratr_idx = RATEID_IDX_BGN_20M_1SS_BN; |
7292 | } |
7293 | |
7294 | if (priv->tx_paths == 2 && priv->rx_paths == 2) { |
7295 | if (rssi_level == RTL8XXXU_RATR_STA_HIGH) { |
7296 | rate_bitmap &= 0x0f8f0000; |
7297 | } else if (rssi_level == RTL8XXXU_RATR_STA_MID) { |
7298 | rate_bitmap &= 0x0f8ff000; |
7299 | } else { |
7300 | if (txbw_40mhz) |
7301 | rate_bitmap &= 0x0f8ff015; |
7302 | else |
7303 | rate_bitmap &= 0x0f8ff005; |
7304 | } |
7305 | } else { |
7306 | if (rssi_level == RTL8XXXU_RATR_STA_HIGH) { |
7307 | rate_bitmap &= 0x000f0000; |
7308 | } else if (rssi_level == RTL8XXXU_RATR_STA_MID) { |
7309 | rate_bitmap &= 0x000ff000; |
7310 | } else { |
7311 | if (txbw_40mhz) |
7312 | rate_bitmap &= 0x000ff015; |
7313 | else |
7314 | rate_bitmap &= 0x000ff005; |
7315 | } |
7316 | } |
7317 | break; |
7318 | default: |
7319 | ratr_idx = RATEID_IDX_BGN_40M_2SS; |
7320 | rate_bitmap &= 0x0fffffff; |
7321 | break; |
7322 | } |
7323 | |
7324 | sta_info->rssi_level = rssi_level; |
7325 | priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid); |
7326 | } |
7327 | } |
7328 | |
7329 | static void rtl8xxxu_set_atc_status(struct rtl8xxxu_priv *priv, bool atc_status) |
7330 | { |
7331 | struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; |
7332 | u32 val32; |
7333 | |
7334 | if (atc_status == cfo->atc_status) |
7335 | return; |
7336 | |
7337 | cfo->atc_status = atc_status; |
7338 | |
7339 | val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING); |
7340 | if (atc_status) |
7341 | val32 |= CFO_TRACKING_ATC_STATUS; |
7342 | else |
7343 | val32 &= ~CFO_TRACKING_ATC_STATUS; |
7344 | rtl8xxxu_write32(priv, REG_OFDM1_CFO_TRACKING, val: val32); |
7345 | } |
7346 | |
7347 | /* Central frequency offset correction */ |
7348 | static void rtl8xxxu_track_cfo(struct rtl8xxxu_priv *priv) |
7349 | { |
7350 | struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; |
7351 | int cfo_khz_a, cfo_khz_b, cfo_average; |
7352 | int crystal_cap; |
7353 | |
7354 | if (!rtl8xxxu_is_assoc(priv)) { |
7355 | /* Reset */ |
7356 | cfo->adjust = true; |
7357 | |
7358 | if (cfo->crystal_cap > priv->default_crystal_cap) |
7359 | priv->fops->set_crystal_cap(priv, cfo->crystal_cap - 1); |
7360 | else if (cfo->crystal_cap < priv->default_crystal_cap) |
7361 | priv->fops->set_crystal_cap(priv, cfo->crystal_cap + 1); |
7362 | |
7363 | rtl8xxxu_set_atc_status(priv, atc_status: true); |
7364 | |
7365 | return; |
7366 | } |
7367 | |
7368 | if (cfo->packet_count == cfo->packet_count_pre) |
7369 | /* No new information. */ |
7370 | return; |
7371 | |
7372 | cfo->packet_count_pre = cfo->packet_count; |
7373 | |
7374 | /* CFO_tail[1:0] is S(8,7), (num_subcarrier>>7) x 312.5K = CFO value(K Hz) */ |
7375 | cfo_khz_a = (int)((cfo->cfo_tail[0] * 3125) / 10) >> 7; |
7376 | cfo_khz_b = (int)((cfo->cfo_tail[1] * 3125) / 10) >> 7; |
7377 | |
7378 | if (priv->tx_paths == 1) |
7379 | cfo_average = cfo_khz_a; |
7380 | else |
7381 | cfo_average = (cfo_khz_a + cfo_khz_b) / 2; |
7382 | |
7383 | dev_dbg(&priv->udev->dev, "cfo_average: %d\n" , cfo_average); |
7384 | |
7385 | if (cfo->adjust) { |
7386 | if (abs(cfo_average) < CFO_TH_XTAL_LOW) |
7387 | cfo->adjust = false; |
7388 | } else { |
7389 | if (abs(cfo_average) > CFO_TH_XTAL_HIGH) |
7390 | cfo->adjust = true; |
7391 | } |
7392 | |
7393 | /* |
7394 | * TODO: We should return here only if bluetooth is enabled. |
7395 | * See the vendor drivers for how to determine that. |
7396 | */ |
7397 | if (priv->has_bluetooth) |
7398 | return; |
7399 | |
7400 | if (!cfo->adjust) |
7401 | return; |
7402 | |
7403 | crystal_cap = cfo->crystal_cap; |
7404 | |
7405 | if (cfo_average > CFO_TH_XTAL_LOW) |
7406 | crystal_cap++; |
7407 | else if (cfo_average < -CFO_TH_XTAL_LOW) |
7408 | crystal_cap--; |
7409 | |
7410 | crystal_cap = clamp(crystal_cap, 0, 0x3f); |
7411 | |
7412 | priv->fops->set_crystal_cap(priv, crystal_cap); |
7413 | |
7414 | rtl8xxxu_set_atc_status(priv, abs(cfo_average) >= CFO_TH_ATC); |
7415 | } |
7416 | |
7417 | static void rtl8xxxu_ra_iter(void *data, struct ieee80211_sta *sta) |
7418 | { |
7419 | struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
7420 | struct rtl8xxxu_priv *priv = data; |
7421 | int signal = -ewma_rssi_read(e: &sta_info->avg_rssi); |
7422 | |
7423 | priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta), |
7424 | rtl8xxxu_signal_to_snr(signal)); |
7425 | rtl8xxxu_refresh_rate_mask(priv, signal, sta, force: false); |
7426 | } |
7427 | |
7428 | struct rtl8xxxu_stas_entry { |
7429 | struct list_head list; |
7430 | struct ieee80211_sta *sta; |
7431 | }; |
7432 | |
7433 | struct rtl8xxxu_iter_stas_data { |
7434 | struct rtl8xxxu_priv *priv; |
7435 | struct list_head list; |
7436 | }; |
7437 | |
7438 | static void rtl8xxxu_collect_sta_iter(void *data, struct ieee80211_sta *sta) |
7439 | { |
7440 | struct rtl8xxxu_iter_stas_data *iter_stas = data; |
7441 | struct rtl8xxxu_stas_entry *stas_entry; |
7442 | |
7443 | stas_entry = kmalloc(size: sizeof(*stas_entry), GFP_ATOMIC); |
7444 | if (!stas_entry) |
7445 | return; |
7446 | |
7447 | stas_entry->sta = sta; |
7448 | list_add_tail(new: &stas_entry->list, head: &iter_stas->list); |
7449 | } |
7450 | |
7451 | static void rtl8xxxu_watchdog_callback(struct work_struct *work) |
7452 | { |
7453 | |
7454 | struct rtl8xxxu_iter_stas_data iter_data; |
7455 | struct rtl8xxxu_stas_entry *sta_entry, *tmp; |
7456 | struct rtl8xxxu_priv *priv; |
7457 | |
7458 | priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work); |
7459 | iter_data.priv = priv; |
7460 | INIT_LIST_HEAD(list: &iter_data.list); |
7461 | |
7462 | mutex_lock(&priv->sta_mutex); |
7463 | ieee80211_iterate_stations_atomic(hw: priv->hw, iterator: rtl8xxxu_collect_sta_iter, |
7464 | data: &iter_data); |
7465 | list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, list) { |
7466 | list_del_init(entry: &sta_entry->list); |
7467 | rtl8xxxu_ra_iter(data: priv, sta: sta_entry->sta); |
7468 | kfree(objp: sta_entry); |
7469 | } |
7470 | mutex_unlock(lock: &priv->sta_mutex); |
7471 | |
7472 | if (priv->fops->set_crystal_cap) |
7473 | rtl8xxxu_track_cfo(priv); |
7474 | |
7475 | schedule_delayed_work(dwork: &priv->ra_watchdog, delay: 2 * HZ); |
7476 | } |
7477 | |
7478 | static int rtl8xxxu_start(struct ieee80211_hw *hw) |
7479 | { |
7480 | struct rtl8xxxu_priv *priv = hw->priv; |
7481 | struct rtl8xxxu_rx_urb *rx_urb; |
7482 | struct rtl8xxxu_tx_urb *tx_urb; |
7483 | struct sk_buff *skb; |
7484 | unsigned long flags; |
7485 | int ret, i; |
7486 | |
7487 | ret = 0; |
7488 | |
7489 | init_usb_anchor(anchor: &priv->rx_anchor); |
7490 | init_usb_anchor(anchor: &priv->tx_anchor); |
7491 | init_usb_anchor(anchor: &priv->int_anchor); |
7492 | |
7493 | priv->fops->enable_rf(priv); |
7494 | if (priv->usb_interrupts) { |
7495 | ret = rtl8xxxu_submit_int_urb(hw); |
7496 | if (ret) |
7497 | goto exit; |
7498 | } |
7499 | |
7500 | for (i = 0; i < RTL8XXXU_TX_URBS; i++) { |
7501 | tx_urb = kmalloc(size: sizeof(struct rtl8xxxu_tx_urb), GFP_KERNEL); |
7502 | if (!tx_urb) { |
7503 | if (!i) |
7504 | ret = -ENOMEM; |
7505 | |
7506 | goto error_out; |
7507 | } |
7508 | usb_init_urb(urb: &tx_urb->urb); |
7509 | INIT_LIST_HEAD(list: &tx_urb->list); |
7510 | tx_urb->hw = hw; |
7511 | list_add(new: &tx_urb->list, head: &priv->tx_urb_free_list); |
7512 | priv->tx_urb_free_count++; |
7513 | } |
7514 | |
7515 | priv->tx_stopped = false; |
7516 | |
7517 | spin_lock_irqsave(&priv->rx_urb_lock, flags); |
7518 | priv->shutdown = false; |
7519 | spin_unlock_irqrestore(lock: &priv->rx_urb_lock, flags); |
7520 | |
7521 | for (i = 0; i < RTL8XXXU_RX_URBS; i++) { |
7522 | rx_urb = kmalloc(size: sizeof(struct rtl8xxxu_rx_urb), GFP_KERNEL); |
7523 | if (!rx_urb) { |
7524 | if (!i) |
7525 | ret = -ENOMEM; |
7526 | |
7527 | goto error_out; |
7528 | } |
7529 | usb_init_urb(urb: &rx_urb->urb); |
7530 | INIT_LIST_HEAD(list: &rx_urb->list); |
7531 | rx_urb->hw = hw; |
7532 | |
7533 | ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); |
7534 | if (ret) { |
7535 | if (ret != -ENOMEM) { |
7536 | skb = (struct sk_buff *)rx_urb->urb.context; |
7537 | dev_kfree_skb(skb); |
7538 | } |
7539 | rtl8xxxu_queue_rx_urb(priv, rx_urb); |
7540 | } |
7541 | } |
7542 | |
7543 | schedule_delayed_work(dwork: &priv->ra_watchdog, delay: 2 * HZ); |
7544 | exit: |
7545 | /* |
7546 | * Accept all data and mgmt frames |
7547 | */ |
7548 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, val: 0xffff); |
7549 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, val: 0xffff); |
7550 | |
7551 | rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, |
7552 | OFDM0_X_AGC_CORE1_IGI_MASK, val: 0x1e); |
7553 | |
7554 | return ret; |
7555 | |
7556 | error_out: |
7557 | rtl8xxxu_free_tx_resources(priv); |
7558 | /* |
7559 | * Disable all data and mgmt frames |
7560 | */ |
7561 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, val: 0x0000); |
7562 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, val: 0x0000); |
7563 | |
7564 | return ret; |
7565 | } |
7566 | |
7567 | static void rtl8xxxu_stop(struct ieee80211_hw *hw) |
7568 | { |
7569 | struct rtl8xxxu_priv *priv = hw->priv; |
7570 | unsigned long flags; |
7571 | |
7572 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0xff); |
7573 | |
7574 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, val: 0x0000); |
7575 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, val: 0x0000); |
7576 | |
7577 | spin_lock_irqsave(&priv->rx_urb_lock, flags); |
7578 | priv->shutdown = true; |
7579 | spin_unlock_irqrestore(lock: &priv->rx_urb_lock, flags); |
7580 | |
7581 | usb_kill_anchored_urbs(anchor: &priv->rx_anchor); |
7582 | usb_kill_anchored_urbs(anchor: &priv->tx_anchor); |
7583 | if (priv->usb_interrupts) |
7584 | usb_kill_anchored_urbs(anchor: &priv->int_anchor); |
7585 | |
7586 | rtl8xxxu_write8(priv, REG_TXPAUSE, val: 0xff); |
7587 | |
7588 | priv->fops->disable_rf(priv); |
7589 | |
7590 | /* |
7591 | * Disable interrupts |
7592 | */ |
7593 | if (priv->usb_interrupts) |
7594 | rtl8xxxu_write32(priv, REG_USB_HIMR, val: 0); |
7595 | |
7596 | cancel_work_sync(work: &priv->c2hcmd_work); |
7597 | cancel_delayed_work_sync(dwork: &priv->ra_watchdog); |
7598 | cancel_delayed_work_sync(dwork: &priv->update_beacon_work); |
7599 | |
7600 | rtl8xxxu_free_rx_resources(priv); |
7601 | rtl8xxxu_free_tx_resources(priv); |
7602 | } |
7603 | |
7604 | static int rtl8xxxu_sta_add(struct ieee80211_hw *hw, |
7605 | struct ieee80211_vif *vif, |
7606 | struct ieee80211_sta *sta) |
7607 | { |
7608 | struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
7609 | struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv; |
7610 | struct rtl8xxxu_priv *priv = hw->priv; |
7611 | |
7612 | mutex_lock(&priv->sta_mutex); |
7613 | ewma_rssi_init(e: &sta_info->avg_rssi); |
7614 | if (vif->type == NL80211_IFTYPE_AP) { |
7615 | sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT; |
7616 | sta_info->macid = rtl8xxxu_acquire_macid(priv); |
7617 | if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM) { |
7618 | mutex_unlock(lock: &priv->sta_mutex); |
7619 | return -ENOSPC; |
7620 | } |
7621 | |
7622 | rtl8xxxu_refresh_rate_mask(priv, signal: 0, sta, force: true); |
7623 | priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true); |
7624 | } else { |
7625 | switch (rtlvif->port_num) { |
7626 | case 0: |
7627 | sta_info->macid = RTL8XXXU_BC_MC_MACID; |
7628 | break; |
7629 | case 1: |
7630 | sta_info->macid = RTL8XXXU_BC_MC_MACID1; |
7631 | break; |
7632 | default: |
7633 | break; |
7634 | } |
7635 | } |
7636 | mutex_unlock(lock: &priv->sta_mutex); |
7637 | |
7638 | return 0; |
7639 | } |
7640 | |
7641 | static int rtl8xxxu_sta_remove(struct ieee80211_hw *hw, |
7642 | struct ieee80211_vif *vif, |
7643 | struct ieee80211_sta *sta) |
7644 | { |
7645 | struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; |
7646 | struct rtl8xxxu_priv *priv = hw->priv; |
7647 | |
7648 | mutex_lock(&priv->sta_mutex); |
7649 | if (vif->type == NL80211_IFTYPE_AP) |
7650 | rtl8xxxu_release_macid(priv, macid: sta_info->macid); |
7651 | mutex_unlock(lock: &priv->sta_mutex); |
7652 | |
7653 | return 0; |
7654 | } |
7655 | |
7656 | static const struct ieee80211_ops rtl8xxxu_ops = { |
7657 | .add_chanctx = ieee80211_emulate_add_chanctx, |
7658 | .remove_chanctx = ieee80211_emulate_remove_chanctx, |
7659 | .change_chanctx = ieee80211_emulate_change_chanctx, |
7660 | .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, |
7661 | .tx = rtl8xxxu_tx, |
7662 | .wake_tx_queue = ieee80211_handle_wake_tx_queue, |
7663 | .add_interface = rtl8xxxu_add_interface, |
7664 | .remove_interface = rtl8xxxu_remove_interface, |
7665 | .config = rtl8xxxu_config, |
7666 | .conf_tx = rtl8xxxu_conf_tx, |
7667 | .bss_info_changed = rtl8xxxu_bss_info_changed, |
7668 | .start_ap = rtl8xxxu_start_ap, |
7669 | .configure_filter = rtl8xxxu_configure_filter, |
7670 | .set_rts_threshold = rtl8xxxu_set_rts_threshold, |
7671 | .start = rtl8xxxu_start, |
7672 | .stop = rtl8xxxu_stop, |
7673 | .sw_scan_start = rtl8xxxu_sw_scan_start, |
7674 | .sw_scan_complete = rtl8xxxu_sw_scan_complete, |
7675 | .set_key = rtl8xxxu_set_key, |
7676 | .ampdu_action = rtl8xxxu_ampdu_action, |
7677 | .sta_statistics = rtl8xxxu_sta_statistics, |
7678 | .get_antenna = rtl8xxxu_get_antenna, |
7679 | .set_tim = rtl8xxxu_set_tim, |
7680 | .sta_add = rtl8xxxu_sta_add, |
7681 | .sta_remove = rtl8xxxu_sta_remove, |
7682 | }; |
7683 | |
7684 | static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, |
7685 | struct usb_interface *interface) |
7686 | { |
7687 | struct usb_interface_descriptor *interface_desc; |
7688 | struct usb_host_interface *host_interface; |
7689 | struct usb_endpoint_descriptor *endpoint; |
7690 | struct device *dev = &priv->udev->dev; |
7691 | int i, j = 0, endpoints; |
7692 | u8 dir, xtype, num; |
7693 | int ret = 0; |
7694 | |
7695 | host_interface = interface->cur_altsetting; |
7696 | interface_desc = &host_interface->desc; |
7697 | endpoints = interface_desc->bNumEndpoints; |
7698 | |
7699 | for (i = 0; i < endpoints; i++) { |
7700 | endpoint = &host_interface->endpoint[i].desc; |
7701 | |
7702 | dir = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; |
7703 | num = usb_endpoint_num(epd: endpoint); |
7704 | xtype = usb_endpoint_type(epd: endpoint); |
7705 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) |
7706 | dev_dbg(dev, |
7707 | "%s: endpoint: dir %02x, # %02x, type %02x\n" , |
7708 | __func__, dir, num, xtype); |
7709 | if (usb_endpoint_dir_in(epd: endpoint) && |
7710 | usb_endpoint_xfer_bulk(epd: endpoint)) { |
7711 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) |
7712 | dev_dbg(dev, "%s: in endpoint num %i\n" , |
7713 | __func__, num); |
7714 | |
7715 | if (priv->pipe_in) { |
7716 | dev_warn(dev, |
7717 | "%s: Too many IN pipes\n" , __func__); |
7718 | ret = -EINVAL; |
7719 | goto exit; |
7720 | } |
7721 | |
7722 | priv->pipe_in = usb_rcvbulkpipe(priv->udev, num); |
7723 | } |
7724 | |
7725 | if (usb_endpoint_dir_in(epd: endpoint) && |
7726 | usb_endpoint_xfer_int(epd: endpoint)) { |
7727 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) |
7728 | dev_dbg(dev, "%s: interrupt endpoint num %i\n" , |
7729 | __func__, num); |
7730 | |
7731 | if (priv->pipe_interrupt) { |
7732 | dev_warn(dev, "%s: Too many INTERRUPT pipes\n" , |
7733 | __func__); |
7734 | ret = -EINVAL; |
7735 | goto exit; |
7736 | } |
7737 | |
7738 | priv->pipe_interrupt = usb_rcvintpipe(priv->udev, num); |
7739 | } |
7740 | |
7741 | if (usb_endpoint_dir_out(epd: endpoint) && |
7742 | usb_endpoint_xfer_bulk(epd: endpoint)) { |
7743 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) |
7744 | dev_dbg(dev, "%s: out endpoint num %i\n" , |
7745 | __func__, num); |
7746 | if (j >= RTL8XXXU_OUT_ENDPOINTS) { |
7747 | dev_warn(dev, |
7748 | "%s: Too many OUT pipes\n" , __func__); |
7749 | ret = -EINVAL; |
7750 | goto exit; |
7751 | } |
7752 | priv->out_ep[j++] = num; |
7753 | } |
7754 | } |
7755 | exit: |
7756 | priv->nr_out_eps = j; |
7757 | return ret; |
7758 | } |
7759 | |
7760 | static void rtl8xxxu_init_led(struct rtl8xxxu_priv *priv) |
7761 | { |
7762 | struct led_classdev *led = &priv->led_cdev; |
7763 | |
7764 | if (!priv->fops->led_classdev_brightness_set) |
7765 | return; |
7766 | |
7767 | led->brightness_set_blocking = priv->fops->led_classdev_brightness_set; |
7768 | |
7769 | snprintf(buf: priv->led_name, size: sizeof(priv->led_name), |
7770 | fmt: "rtl8xxxu-usb%s" , dev_name(dev: &priv->udev->dev)); |
7771 | led->name = priv->led_name; |
7772 | led->max_brightness = RTL8XXXU_HW_LED_CONTROL; |
7773 | |
7774 | if (led_classdev_register(parent: &priv->udev->dev, led_cdev: led)) |
7775 | return; |
7776 | |
7777 | priv->led_registered = true; |
7778 | |
7779 | led->brightness = led->max_brightness; |
7780 | priv->fops->led_classdev_brightness_set(led, led->brightness); |
7781 | } |
7782 | |
7783 | static void rtl8xxxu_deinit_led(struct rtl8xxxu_priv *priv) |
7784 | { |
7785 | struct led_classdev *led = &priv->led_cdev; |
7786 | |
7787 | if (!priv->led_registered) |
7788 | return; |
7789 | |
7790 | priv->fops->led_classdev_brightness_set(led, LED_OFF); |
7791 | led_classdev_unregister(led_cdev: led); |
7792 | } |
7793 | |
7794 | static const struct ieee80211_iface_limit rtl8xxxu_limits[] = { |
7795 | { .max = 2, .types = BIT(NL80211_IFTYPE_STATION), }, |
7796 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP), }, |
7797 | }; |
7798 | |
7799 | static const struct ieee80211_iface_combination rtl8xxxu_combinations[] = { |
7800 | { |
7801 | .limits = rtl8xxxu_limits, |
7802 | .n_limits = ARRAY_SIZE(rtl8xxxu_limits), |
7803 | .max_interfaces = 2, |
7804 | .num_different_channels = 1, |
7805 | }, |
7806 | }; |
7807 | |
7808 | static int rtl8xxxu_probe(struct usb_interface *interface, |
7809 | const struct usb_device_id *id) |
7810 | { |
7811 | struct rtl8xxxu_priv *priv; |
7812 | struct ieee80211_hw *hw; |
7813 | struct usb_device *udev; |
7814 | struct ieee80211_supported_band *sband; |
7815 | int ret; |
7816 | int untested = 1; |
7817 | |
7818 | udev = usb_get_dev(interface_to_usbdev(interface)); |
7819 | |
7820 | switch (id->idVendor) { |
7821 | case USB_VENDOR_ID_REALTEK: |
7822 | switch(id->idProduct) { |
7823 | case 0x1724: |
7824 | case 0x8176: |
7825 | case 0x8178: |
7826 | case 0x817f: |
7827 | case 0x818b: |
7828 | case 0xf179: |
7829 | case 0x8179: |
7830 | case 0xb711: |
7831 | case 0xf192: |
7832 | case 0x2005: |
7833 | untested = 0; |
7834 | break; |
7835 | } |
7836 | break; |
7837 | case 0x7392: |
7838 | if (id->idProduct == 0x7811 || id->idProduct == 0xa611 || id->idProduct == 0xb811) |
7839 | untested = 0; |
7840 | break; |
7841 | case 0x050d: |
7842 | if (id->idProduct == 0x1004) |
7843 | untested = 0; |
7844 | break; |
7845 | case 0x20f4: |
7846 | if (id->idProduct == 0x648b) |
7847 | untested = 0; |
7848 | break; |
7849 | case 0x2001: |
7850 | if (id->idProduct == 0x3308) |
7851 | untested = 0; |
7852 | break; |
7853 | case 0x2357: |
7854 | if (id->idProduct == 0x0109 || id->idProduct == 0x0135) |
7855 | untested = 0; |
7856 | break; |
7857 | case 0x0b05: |
7858 | if (id->idProduct == 0x18f1) |
7859 | untested = 0; |
7860 | break; |
7861 | default: |
7862 | break; |
7863 | } |
7864 | |
7865 | if (untested) { |
7866 | rtl8xxxu_debug |= RTL8XXXU_DEBUG_EFUSE; |
7867 | dev_info(&udev->dev, |
7868 | "This Realtek USB WiFi dongle (0x%04x:0x%04x) is untested!\n" , |
7869 | id->idVendor, id->idProduct); |
7870 | dev_info(&udev->dev, |
7871 | "Please report results to Jes.Sorensen@gmail.com\n" ); |
7872 | } |
7873 | |
7874 | hw = ieee80211_alloc_hw(priv_data_len: sizeof(struct rtl8xxxu_priv), ops: &rtl8xxxu_ops); |
7875 | if (!hw) { |
7876 | ret = -ENOMEM; |
7877 | goto err_put_dev; |
7878 | } |
7879 | |
7880 | priv = hw->priv; |
7881 | priv->hw = hw; |
7882 | priv->udev = udev; |
7883 | priv->fops = (struct rtl8xxxu_fileops *)id->driver_info; |
7884 | mutex_init(&priv->usb_buf_mutex); |
7885 | mutex_init(&priv->syson_indirect_access_mutex); |
7886 | mutex_init(&priv->h2c_mutex); |
7887 | mutex_init(&priv->sta_mutex); |
7888 | INIT_LIST_HEAD(list: &priv->tx_urb_free_list); |
7889 | spin_lock_init(&priv->tx_urb_lock); |
7890 | INIT_LIST_HEAD(list: &priv->rx_urb_pending_list); |
7891 | spin_lock_init(&priv->rx_urb_lock); |
7892 | INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); |
7893 | INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); |
7894 | INIT_DELAYED_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback); |
7895 | skb_queue_head_init(list: &priv->c2hcmd_queue); |
7896 | |
7897 | usb_set_intfdata(intf: interface, data: hw); |
7898 | |
7899 | ret = rtl8xxxu_parse_usb(priv, interface); |
7900 | if (ret) |
7901 | goto err_set_intfdata; |
7902 | |
7903 | ret = priv->fops->identify_chip(priv); |
7904 | if (ret) { |
7905 | dev_err(&udev->dev, "Fatal - failed to identify chip\n" ); |
7906 | goto err_set_intfdata; |
7907 | } |
7908 | |
7909 | hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1; |
7910 | hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1; |
7911 | |
7912 | if (priv->rtl_chip == RTL8188E) |
7913 | INIT_WORK(&priv->c2hcmd_work, rtl8188e_c2hcmd_callback); |
7914 | else |
7915 | INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback); |
7916 | |
7917 | ret = priv->fops->read_efuse(priv); |
7918 | if (ret) { |
7919 | dev_err(&udev->dev, "Fatal - failed to read EFuse\n" ); |
7920 | goto err_set_intfdata; |
7921 | } |
7922 | |
7923 | ret = priv->fops->parse_efuse(priv); |
7924 | if (ret) { |
7925 | dev_err(&udev->dev, "Fatal - failed to parse EFuse\n" ); |
7926 | goto err_set_intfdata; |
7927 | } |
7928 | |
7929 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) |
7930 | rtl8xxxu_dump_efuse(priv); |
7931 | |
7932 | rtl8xxxu_print_chipinfo(priv); |
7933 | |
7934 | ret = priv->fops->load_firmware(priv); |
7935 | if (ret) { |
7936 | dev_err(&udev->dev, "Fatal - failed to load firmware\n" ); |
7937 | goto err_set_intfdata; |
7938 | } |
7939 | |
7940 | ret = rtl8xxxu_init_device(hw); |
7941 | if (ret) |
7942 | goto err_set_intfdata; |
7943 | |
7944 | hw->vif_data_size = sizeof(struct rtl8xxxu_vif); |
7945 | |
7946 | hw->wiphy->max_scan_ssids = 1; |
7947 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; |
7948 | if (priv->fops->max_macid_num) |
7949 | hw->wiphy->max_ap_assoc_sta = priv->fops->max_macid_num - 1; |
7950 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
7951 | if (priv->fops->supports_ap) |
7952 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); |
7953 | hw->queues = 4; |
7954 | |
7955 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; |
7956 | |
7957 | if (priv->fops->supports_concurrent) { |
7958 | hw->wiphy->iface_combinations = rtl8xxxu_combinations; |
7959 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtl8xxxu_combinations); |
7960 | } |
7961 | |
7962 | sband = &rtl8xxxu_supported_band; |
7963 | sband->ht_cap.ht_supported = true; |
7964 | sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
7965 | sband->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; |
7966 | sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40; |
7967 | memset(&sband->ht_cap.mcs, 0, sizeof(sband->ht_cap.mcs)); |
7968 | sband->ht_cap.mcs.rx_mask[0] = 0xff; |
7969 | sband->ht_cap.mcs.rx_mask[4] = 0x01; |
7970 | if (priv->rf_paths > 1) { |
7971 | sband->ht_cap.mcs.rx_mask[1] = 0xff; |
7972 | sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; |
7973 | } |
7974 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
7975 | /* |
7976 | * Some APs will negotiate HT20_40 in a noisy environment leading |
7977 | * to miserable performance. Rather than defaulting to this, only |
7978 | * enable it if explicitly requested at module load time. |
7979 | */ |
7980 | if (rtl8xxxu_ht40_2g) { |
7981 | dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n" ); |
7982 | sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
7983 | } |
7984 | hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; |
7985 | |
7986 | hw->wiphy->rts_threshold = 2347; |
7987 | |
7988 | SET_IEEE80211_DEV(hw: priv->hw, dev: &interface->dev); |
7989 | SET_IEEE80211_PERM_ADDR(hw, addr: priv->mac_addr); |
7990 | |
7991 | hw->extra_tx_headroom = priv->fops->tx_desc_size; |
7992 | ieee80211_hw_set(hw, SIGNAL_DBM); |
7993 | |
7994 | /* |
7995 | * The firmware handles rate control, except for RTL8188EU, |
7996 | * where we handle the rate control in the driver. |
7997 | */ |
7998 | ieee80211_hw_set(hw, HAS_RATE_CONTROL); |
7999 | ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); |
8000 | ieee80211_hw_set(hw, AMPDU_AGGREGATION); |
8001 | |
8002 | wiphy_ext_feature_set(wiphy: hw->wiphy, ftidx: NL80211_EXT_FEATURE_CQM_RSSI_LIST); |
8003 | |
8004 | ret = ieee80211_register_hw(hw: priv->hw); |
8005 | if (ret) { |
8006 | dev_err(&udev->dev, "%s: Failed to register: %i\n" , |
8007 | __func__, ret); |
8008 | goto err_set_intfdata; |
8009 | } |
8010 | |
8011 | rtl8xxxu_init_led(priv); |
8012 | |
8013 | return 0; |
8014 | |
8015 | err_set_intfdata: |
8016 | usb_set_intfdata(intf: interface, NULL); |
8017 | |
8018 | kfree(objp: priv->fw_data); |
8019 | mutex_destroy(lock: &priv->usb_buf_mutex); |
8020 | mutex_destroy(lock: &priv->syson_indirect_access_mutex); |
8021 | mutex_destroy(lock: &priv->h2c_mutex); |
8022 | |
8023 | ieee80211_free_hw(hw); |
8024 | err_put_dev: |
8025 | usb_put_dev(dev: udev); |
8026 | |
8027 | return ret; |
8028 | } |
8029 | |
8030 | static void rtl8xxxu_disconnect(struct usb_interface *interface) |
8031 | { |
8032 | struct rtl8xxxu_priv *priv; |
8033 | struct ieee80211_hw *hw; |
8034 | |
8035 | hw = usb_get_intfdata(intf: interface); |
8036 | priv = hw->priv; |
8037 | |
8038 | rtl8xxxu_deinit_led(priv); |
8039 | |
8040 | ieee80211_unregister_hw(hw); |
8041 | |
8042 | priv->fops->power_off(priv); |
8043 | |
8044 | usb_set_intfdata(intf: interface, NULL); |
8045 | |
8046 | dev_info(&priv->udev->dev, "disconnecting\n" ); |
8047 | |
8048 | kfree(objp: priv->fw_data); |
8049 | mutex_destroy(lock: &priv->usb_buf_mutex); |
8050 | mutex_destroy(lock: &priv->syson_indirect_access_mutex); |
8051 | mutex_destroy(lock: &priv->h2c_mutex); |
8052 | |
8053 | if (priv->udev->state != USB_STATE_NOTATTACHED) { |
8054 | dev_info(&priv->udev->dev, |
8055 | "Device still attached, trying to reset\n" ); |
8056 | usb_reset_device(dev: priv->udev); |
8057 | } |
8058 | usb_put_dev(dev: priv->udev); |
8059 | ieee80211_free_hw(hw); |
8060 | } |
8061 | |
8062 | static const struct usb_device_id dev_table[] = { |
8063 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8724, 0xff, 0xff, 0xff), |
8064 | .driver_info = (unsigned long)&rtl8723au_fops}, |
8065 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1724, 0xff, 0xff, 0xff), |
8066 | .driver_info = (unsigned long)&rtl8723au_fops}, |
8067 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0724, 0xff, 0xff, 0xff), |
8068 | .driver_info = (unsigned long)&rtl8723au_fops}, |
8069 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818b, 0xff, 0xff, 0xff), |
8070 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8071 | /* TP-Link TL-WN822N v4 */ |
8072 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0108, 0xff, 0xff, 0xff), |
8073 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8074 | /* D-Link DWA-131 rev E1, tested by David Patiño */ |
8075 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3319, 0xff, 0xff, 0xff), |
8076 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8077 | /* Tested by Myckel Habets */ |
8078 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0109, 0xff, 0xff, 0xff), |
8079 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8080 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xb720, 0xff, 0xff, 0xff), |
8081 | .driver_info = (unsigned long)&rtl8723bu_fops}, |
8082 | {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa611, 0xff, 0xff, 0xff), |
8083 | .driver_info = (unsigned long)&rtl8723bu_fops}, |
8084 | /* RTL8188FU */ |
8085 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf179, 0xff, 0xff, 0xff), |
8086 | .driver_info = (unsigned long)&rtl8188fu_fops}, |
8087 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8179, 0xff, 0xff, 0xff), |
8088 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8089 | /* Tested by Hans de Goede - rtl8188etv */ |
8090 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0179, 0xff, 0xff, 0xff), |
8091 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8092 | /* Sitecom rtl8188eus */ |
8093 | {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0076, 0xff, 0xff, 0xff), |
8094 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8095 | /* D-Link USB-GO-N150 */ |
8096 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3311, 0xff, 0xff, 0xff), |
8097 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8098 | /* D-Link DWA-125 REV D1 */ |
8099 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330f, 0xff, 0xff, 0xff), |
8100 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8101 | /* D-Link DWA-123 REV D1 */ |
8102 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3310, 0xff, 0xff, 0xff), |
8103 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8104 | /* D-Link DWA-121 rev B1 */ |
8105 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331b, 0xff, 0xff, 0xff), |
8106 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8107 | /* Abocom - Abocom */ |
8108 | {USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8179, 0xff, 0xff, 0xff), |
8109 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8110 | /* Elecom WDC-150SU2M */ |
8111 | {USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4008, 0xff, 0xff, 0xff), |
8112 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8113 | /* TP-Link TL-WN722N v2 */ |
8114 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010c, 0xff, 0xff, 0xff), |
8115 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8116 | /* TP-Link TL-WN727N v5.21 */ |
8117 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0111, 0xff, 0xff, 0xff), |
8118 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8119 | /* MERCUSYS MW150US v2 */ |
8120 | {USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0102, 0xff, 0xff, 0xff), |
8121 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8122 | /* ASUS USB-N10 Nano B1 */ |
8123 | {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f0, 0xff, 0xff, 0xff), |
8124 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8125 | /* Edimax EW-7811Un V2 */ |
8126 | {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb811, 0xff, 0xff, 0xff), |
8127 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8128 | /* Rosewill USB-N150 Nano */ |
8129 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xffef, 0xff, 0xff, 0xff), |
8130 | .driver_info = (unsigned long)&rtl8188eu_fops}, |
8131 | /* RTL8710BU aka RTL8188GU (not to be confused with RTL8188GTVU) */ |
8132 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xb711, 0xff, 0xff, 0xff), |
8133 | .driver_info = (unsigned long)&rtl8710bu_fops}, |
8134 | /* TOTOLINK N150UA V5 / N150UA-B */ |
8135 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff), |
8136 | .driver_info = (unsigned long)&rtl8710bu_fops}, |
8137 | /* Comfast CF-826F */ |
8138 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf192, 0xff, 0xff, 0xff), |
8139 | .driver_info = (unsigned long)&rtl8192fu_fops}, |
8140 | /* Asus USB-N13 rev C1 */ |
8141 | {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f1, 0xff, 0xff, 0xff), |
8142 | .driver_info = (unsigned long)&rtl8192fu_fops}, |
8143 | /* EDIMAX EW-7722UTn V3 */ |
8144 | {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb722, 0xff, 0xff, 0xff), |
8145 | .driver_info = (unsigned long)&rtl8192fu_fops}, |
8146 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff), |
8147 | .driver_info = (unsigned long)&rtl8192fu_fops}, |
8148 | /* TP-Link TL-WN823N V2 */ |
8149 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff), |
8150 | .driver_info = (unsigned long)&rtl8192fu_fops}, |
8151 | #ifdef CONFIG_RTL8XXXU_UNTESTED |
8152 | /* Still supported by rtlwifi */ |
8153 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), |
8154 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8155 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8178, 0xff, 0xff, 0xff), |
8156 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8157 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817f, 0xff, 0xff, 0xff), |
8158 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8159 | /* Tested by Larry Finger */ |
8160 | {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), |
8161 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8162 | /* Tested by Andrea Merello */ |
8163 | {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), |
8164 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8165 | /* Tested by Jocelyn Mayer */ |
8166 | {USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x648b, 0xff, 0xff, 0xff), |
8167 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8168 | /* Tested by Stefano Bravi */ |
8169 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3308, 0xff, 0xff, 0xff), |
8170 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8171 | /* Currently untested 8188 series devices */ |
8172 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x018a, 0xff, 0xff, 0xff), |
8173 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8174 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), |
8175 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8176 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8170, 0xff, 0xff, 0xff), |
8177 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8178 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8177, 0xff, 0xff, 0xff), |
8179 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8180 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817a, 0xff, 0xff, 0xff), |
8181 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8182 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817b, 0xff, 0xff, 0xff), |
8183 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8184 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817d, 0xff, 0xff, 0xff), |
8185 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8186 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff), |
8187 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8188 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff), |
8189 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8190 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), |
8191 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8192 | {USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0631, 0xff, 0xff, 0xff), |
8193 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8194 | {USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x094c, 0xff, 0xff, 0xff), |
8195 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8196 | {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff), |
8197 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8198 | {USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), |
8199 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8200 | {USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff), |
8201 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8202 | {USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff), |
8203 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8204 | {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff), |
8205 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8206 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff), |
8207 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8208 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x5088, 0xff, 0xff, 0xff), |
8209 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8210 | {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0052, 0xff, 0xff, 0xff), |
8211 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8212 | {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x005c, 0xff, 0xff, 0xff), |
8213 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8214 | {USB_DEVICE_AND_INTERFACE_INFO(0x0eb0, 0x9071, 0xff, 0xff, 0xff), |
8215 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8216 | {USB_DEVICE_AND_INTERFACE_INFO(0x103c, 0x1629, 0xff, 0xff, 0xff), |
8217 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8218 | {USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff), |
8219 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8220 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff), |
8221 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8222 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff), |
8223 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8224 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2a, 0xff, 0xff, 0xff), |
8225 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8226 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2e, 0xff, 0xff, 0xff), |
8227 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8228 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xed17, 0xff, 0xff, 0xff), |
8229 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8230 | {USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0090, 0xff, 0xff, 0xff), |
8231 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8232 | {USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff), |
8233 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8234 | {USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), |
8235 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8236 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), |
8237 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8238 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff), |
8239 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8240 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffa, 0xff, 0xff, 0xff), |
8241 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8242 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff8, 0xff, 0xff, 0xff), |
8243 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8244 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffb, 0xff, 0xff, 0xff), |
8245 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8246 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffc, 0xff, 0xff, 0xff), |
8247 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8248 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x1201, 0xff, 0xff, 0xff), |
8249 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8250 | /* Currently untested 8192 series devices */ |
8251 | {USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff), |
8252 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8253 | {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff), |
8254 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8255 | {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff), |
8256 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8257 | {USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff), |
8258 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8259 | {USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff), |
8260 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8261 | {USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff), |
8262 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8263 | {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0061, 0xff, 0xff, 0xff), |
8264 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8265 | {USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff), |
8266 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8267 | {USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff), |
8268 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8269 | {USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff), |
8270 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8271 | {USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8178, 0xff, 0xff, 0xff), |
8272 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8273 | {USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9021, 0xff, 0xff, 0xff), |
8274 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8275 | {USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0xf001, 0xff, 0xff, 0xff), |
8276 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8277 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2e2e, 0xff, 0xff, 0xff), |
8278 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8279 | {USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0019, 0xff, 0xff, 0xff), |
8280 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8281 | {USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0020, 0xff, 0xff, 0xff), |
8282 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8283 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3307, 0xff, 0xff, 0xff), |
8284 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8285 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3309, 0xff, 0xff, 0xff), |
8286 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8287 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff), |
8288 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8289 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff), |
8290 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8291 | {USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff), |
8292 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8293 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0100, 0xff, 0xff, 0xff), |
8294 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8295 | {USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0091, 0xff, 0xff, 0xff), |
8296 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8297 | {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff), |
8298 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
8299 | /* found in rtl8192eu vendor driver */ |
8300 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0107, 0xff, 0xff, 0xff), |
8301 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8302 | {USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab33, 0xff, 0xff, 0xff), |
8303 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8304 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818c, 0xff, 0xff, 0xff), |
8305 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8306 | /* D-Link DWA-131 rev C1 */ |
8307 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3312, 0xff, 0xff, 0xff), |
8308 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8309 | /* TP-Link TL-WN8200ND V2 */ |
8310 | {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0126, 0xff, 0xff, 0xff), |
8311 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8312 | /* Mercusys MW300UM */ |
8313 | {USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0100, 0xff, 0xff, 0xff), |
8314 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8315 | /* Mercusys MW300UH */ |
8316 | {USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0104, 0xff, 0xff, 0xff), |
8317 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
8318 | #endif |
8319 | { } |
8320 | }; |
8321 | |
8322 | static struct usb_driver rtl8xxxu_driver = { |
8323 | .name = DRIVER_NAME, |
8324 | .probe = rtl8xxxu_probe, |
8325 | .disconnect = rtl8xxxu_disconnect, |
8326 | .id_table = dev_table, |
8327 | .no_dynamic_id = 1, |
8328 | .disable_hub_initiated_lpm = 1, |
8329 | }; |
8330 | |
8331 | MODULE_DEVICE_TABLE(usb, dev_table); |
8332 | |
8333 | module_usb_driver(rtl8xxxu_driver); |
8334 | |