diff options
author | George <george0505@realtek.com> | 2011-02-19 17:29:27 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-02-21 15:39:58 -0500 |
commit | 666e8457fae432ec292e0abc344f8684046fa605 (patch) | |
tree | c0048e06f3890fe65d7770b087be2cb6231c2c64 /drivers/net/wireless/rtlwifi | |
parent | dc0313f46664192c3cbd60e94abb28ab6f00979d (diff) |
rtlwifi: rtl8192cu: Add routine mac
Add the routine rtlwifi/rtl8192cu/hw.c.
Signed-off-by: George <george0505@realtek.com>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | 1144 |
1 files changed, 1144 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c new file mode 100644 index 000000000000..f8514cba17b6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | |||
@@ -0,0 +1,1144 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | ****************************************************************************/ | ||
29 | #include <linux/module.h> | ||
30 | |||
31 | #include "../wifi.h" | ||
32 | #include "../pci.h" | ||
33 | #include "../usb.h" | ||
34 | #include "../ps.h" | ||
35 | #include "../cam.h" | ||
36 | #include "reg.h" | ||
37 | #include "def.h" | ||
38 | #include "phy.h" | ||
39 | #include "rf.h" | ||
40 | #include "dm.h" | ||
41 | #include "mac.h" | ||
42 | #include "trx.h" | ||
43 | |||
44 | /* macro to shorten lines */ | ||
45 | |||
46 | #define LINK_Q ui_link_quality | ||
47 | #define RX_EVM rx_evm_percentage | ||
48 | #define RX_SIGQ rx_mimo_signalquality | ||
49 | |||
50 | |||
51 | void rtl92c_read_chip_version(struct ieee80211_hw *hw) | ||
52 | { | ||
53 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
54 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
55 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
56 | enum version_8192c chip_version = VERSION_UNKNOWN; | ||
57 | u32 value32; | ||
58 | |||
59 | value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); | ||
60 | if (value32 & TRP_VAUX_EN) { | ||
61 | chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C : | ||
62 | VERSION_TEST_CHIP_88C; | ||
63 | } else { | ||
64 | /* Normal mass production chip. */ | ||
65 | chip_version = NORMAL_CHIP; | ||
66 | chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0); | ||
67 | chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0); | ||
68 | /* RTL8723 with BT function. */ | ||
69 | chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0); | ||
70 | if (IS_VENDOR_UMC(chip_version)) | ||
71 | chip_version |= ((value32 & CHIP_VER_RTL_MASK) ? | ||
72 | CHIP_VENDOR_UMC_B_CUT : 0); | ||
73 | if (IS_92C_SERIAL(chip_version)) { | ||
74 | value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); | ||
75 | chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) == | ||
76 | CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0); | ||
77 | } else if (IS_8723_SERIES(chip_version)) { | ||
78 | value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS); | ||
79 | chip_version |= ((value32 & RF_RL_ID) ? | ||
80 | CHIP_8723_DRV_REV : 0); | ||
81 | } | ||
82 | } | ||
83 | rtlhal->version = (enum version_8192c)chip_version; | ||
84 | switch (rtlhal->version) { | ||
85 | case VERSION_NORMAL_TSMC_CHIP_92C_1T2R: | ||
86 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
87 | ("Chip Version ID: VERSION_B_CHIP_92C.\n")); | ||
88 | break; | ||
89 | case VERSION_NORMAL_TSMC_CHIP_92C: | ||
90 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
91 | ("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_92C.\n")); | ||
92 | break; | ||
93 | case VERSION_NORMAL_TSMC_CHIP_88C: | ||
94 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
95 | ("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_88C.\n")); | ||
96 | break; | ||
97 | case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: | ||
98 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
99 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP_i" | ||
100 | "92C_1T2R_A_CUT.\n")); | ||
101 | break; | ||
102 | case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: | ||
103 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
104 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP_" | ||
105 | "92C_A_CUT.\n")); | ||
106 | break; | ||
107 | case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: | ||
108 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
109 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP" | ||
110 | "_88C_A_CUT.\n")); | ||
111 | break; | ||
112 | case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: | ||
113 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
114 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP" | ||
115 | "_92C_1T2R_B_CUT.\n")); | ||
116 | break; | ||
117 | case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: | ||
118 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
119 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP" | ||
120 | "_92C_B_CUT.\n")); | ||
121 | break; | ||
122 | case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: | ||
123 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
124 | ("Chip Version ID: VERSION_NORMAL_UMC_CHIP" | ||
125 | "_88C_B_CUT.\n")); | ||
126 | break; | ||
127 | case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT: | ||
128 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
129 | ("Chip Version ID: VERSION_NORMA_UMC_CHIP" | ||
130 | "_8723_1T1R_A_CUT.\n")); | ||
131 | break; | ||
132 | case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT: | ||
133 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
134 | ("Chip Version ID: VERSION_NORMA_UMC_CHIP" | ||
135 | "_8723_1T1R_B_CUT.\n")); | ||
136 | break; | ||
137 | case VERSION_TEST_CHIP_92C: | ||
138 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
139 | ("Chip Version ID: VERSION_TEST_CHIP_92C.\n")); | ||
140 | break; | ||
141 | case VERSION_TEST_CHIP_88C: | ||
142 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
143 | ("Chip Version ID: VERSION_TEST_CHIP_88C.\n")); | ||
144 | break; | ||
145 | default: | ||
146 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
147 | ("Chip Version ID: ???????????????.\n")); | ||
148 | break; | ||
149 | } | ||
150 | if (IS_92C_SERIAL(rtlhal->version)) | ||
151 | rtlphy->rf_type = | ||
152 | (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R; | ||
153 | else | ||
154 | rtlphy->rf_type = RF_1T1R; | ||
155 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
156 | ("Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? | ||
157 | "RF_2T2R" : "RF_1T1R")); | ||
158 | if (get_rf_type(rtlphy) == RF_1T1R) | ||
159 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
160 | else | ||
161 | rtlpriv->dm.rfpath_rxenable[0] = | ||
162 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
163 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n", | ||
164 | rtlhal->version)); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * writeLLT - LLT table write access | ||
169 | * @io: io callback | ||
170 | * @address: LLT logical address. | ||
171 | * @data: LLT data content | ||
172 | * | ||
173 | * Realtek hardware access function. | ||
174 | * | ||
175 | */ | ||
176 | bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) | ||
177 | { | ||
178 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
179 | bool status = true; | ||
180 | long count = 0; | ||
181 | u32 value = _LLT_INIT_ADDR(address) | | ||
182 | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); | ||
183 | |||
184 | rtl_write_dword(rtlpriv, REG_LLT_INIT, value); | ||
185 | do { | ||
186 | value = rtl_read_dword(rtlpriv, REG_LLT_INIT); | ||
187 | if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) | ||
188 | break; | ||
189 | if (count > POLLING_LLT_THRESHOLD) { | ||
190 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
191 | ("Failed to polling write LLT done at" | ||
192 | " address %d! _LLT_OP_VALUE(%x)\n", | ||
193 | address, _LLT_OP_VALUE(value))); | ||
194 | status = false; | ||
195 | break; | ||
196 | } | ||
197 | } while (++count); | ||
198 | return status; | ||
199 | } | ||
200 | /** | ||
201 | * rtl92c_init_LLT_table - Init LLT table | ||
202 | * @io: io callback | ||
203 | * @boundary: | ||
204 | * | ||
205 | * Realtek hardware access function. | ||
206 | * | ||
207 | */ | ||
208 | bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) | ||
209 | { | ||
210 | bool rst = true; | ||
211 | u32 i; | ||
212 | |||
213 | for (i = 0; i < (boundary - 1); i++) { | ||
214 | rst = rtl92c_llt_write(hw, i , i + 1); | ||
215 | if (true != rst) { | ||
216 | printk(KERN_ERR "===> %s #1 fail\n", __func__); | ||
217 | return rst; | ||
218 | } | ||
219 | } | ||
220 | /* end of list */ | ||
221 | rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF); | ||
222 | if (true != rst) { | ||
223 | printk(KERN_ERR "===> %s #2 fail\n", __func__); | ||
224 | return rst; | ||
225 | } | ||
226 | /* Make the other pages as ring buffer | ||
227 | * This ring buffer is used as beacon buffer if we config this MAC | ||
228 | * as two MAC transfer. | ||
229 | * Otherwise used as local loopback buffer. | ||
230 | */ | ||
231 | for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) { | ||
232 | rst = rtl92c_llt_write(hw, i, (i + 1)); | ||
233 | if (true != rst) { | ||
234 | printk(KERN_ERR "===> %s #3 fail\n", __func__); | ||
235 | return rst; | ||
236 | } | ||
237 | } | ||
238 | /* Let last entry point to the start entry of ring buffer */ | ||
239 | rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary); | ||
240 | if (true != rst) { | ||
241 | printk(KERN_ERR "===> %s #4 fail\n", __func__); | ||
242 | return rst; | ||
243 | } | ||
244 | return rst; | ||
245 | } | ||
246 | void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, | ||
247 | u8 *p_macaddr, bool is_group, u8 enc_algo, | ||
248 | bool is_wepkey, bool clear_all) | ||
249 | { | ||
250 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
251 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
252 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
253 | u8 *macaddr = p_macaddr; | ||
254 | u32 entry_id = 0; | ||
255 | bool is_pairwise = false; | ||
256 | static u8 cam_const_addr[4][6] = { | ||
257 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
258 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | ||
259 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | ||
260 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
261 | }; | ||
262 | static u8 cam_const_broad[] = { | ||
263 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
264 | }; | ||
265 | |||
266 | if (clear_all) { | ||
267 | u8 idx = 0; | ||
268 | u8 cam_offset = 0; | ||
269 | u8 clear_number = 5; | ||
270 | |||
271 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); | ||
272 | for (idx = 0; idx < clear_number; idx++) { | ||
273 | rtl_cam_mark_invalid(hw, cam_offset + idx); | ||
274 | rtl_cam_empty_entry(hw, cam_offset + idx); | ||
275 | if (idx < 5) { | ||
276 | memset(rtlpriv->sec.key_buf[idx], 0, | ||
277 | MAX_KEY_LEN); | ||
278 | rtlpriv->sec.key_len[idx] = 0; | ||
279 | } | ||
280 | } | ||
281 | } else { | ||
282 | switch (enc_algo) { | ||
283 | case WEP40_ENCRYPTION: | ||
284 | enc_algo = CAM_WEP40; | ||
285 | break; | ||
286 | case WEP104_ENCRYPTION: | ||
287 | enc_algo = CAM_WEP104; | ||
288 | break; | ||
289 | case TKIP_ENCRYPTION: | ||
290 | enc_algo = CAM_TKIP; | ||
291 | break; | ||
292 | case AESCCMP_ENCRYPTION: | ||
293 | enc_algo = CAM_AES; | ||
294 | break; | ||
295 | default: | ||
296 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
297 | ("iillegal switch case\n")); | ||
298 | enc_algo = CAM_TKIP; | ||
299 | break; | ||
300 | } | ||
301 | if (is_wepkey || rtlpriv->sec.use_defaultkey) { | ||
302 | macaddr = cam_const_addr[key_index]; | ||
303 | entry_id = key_index; | ||
304 | } else { | ||
305 | if (is_group) { | ||
306 | macaddr = cam_const_broad; | ||
307 | entry_id = key_index; | ||
308 | } else { | ||
309 | key_index = PAIRWISE_KEYIDX; | ||
310 | entry_id = CAM_PAIRWISE_KEY_POSITION; | ||
311 | is_pairwise = true; | ||
312 | } | ||
313 | } | ||
314 | if (rtlpriv->sec.key_len[key_index] == 0) { | ||
315 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
316 | ("delete one entry\n")); | ||
317 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | ||
318 | } else { | ||
319 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
320 | ("The insert KEY length is %d\n", | ||
321 | rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); | ||
322 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
323 | ("The insert KEY is %x %x\n", | ||
324 | rtlpriv->sec.key_buf[0][0], | ||
325 | rtlpriv->sec.key_buf[0][1])); | ||
326 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
327 | ("add one entry\n")); | ||
328 | if (is_pairwise) { | ||
329 | RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, | ||
330 | "Pairwiase Key content :", | ||
331 | rtlpriv->sec.pairwise_key, | ||
332 | rtlpriv->sec. | ||
333 | key_len[PAIRWISE_KEYIDX]); | ||
334 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
335 | ("set Pairwiase key\n")); | ||
336 | |||
337 | rtl_cam_add_one_entry(hw, macaddr, key_index, | ||
338 | entry_id, enc_algo, | ||
339 | CAM_CONFIG_NO_USEDK, | ||
340 | rtlpriv->sec. | ||
341 | key_buf[key_index]); | ||
342 | } else { | ||
343 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
344 | ("set group key\n")); | ||
345 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
346 | rtl_cam_add_one_entry(hw, | ||
347 | rtlefuse->dev_addr, | ||
348 | PAIRWISE_KEYIDX, | ||
349 | CAM_PAIRWISE_KEY_POSITION, | ||
350 | enc_algo, | ||
351 | CAM_CONFIG_NO_USEDK, | ||
352 | rtlpriv->sec.key_buf | ||
353 | [entry_id]); | ||
354 | } | ||
355 | rtl_cam_add_one_entry(hw, macaddr, key_index, | ||
356 | entry_id, enc_algo, | ||
357 | CAM_CONFIG_NO_USEDK, | ||
358 | rtlpriv->sec.key_buf[entry_id]); | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | |||
364 | u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw) | ||
365 | { | ||
366 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
367 | |||
368 | return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS); | ||
369 | } | ||
370 | |||
371 | void rtl92c_enable_interrupt(struct ieee80211_hw *hw) | ||
372 | { | ||
373 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
374 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
375 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
376 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); | ||
377 | |||
378 | if (IS_HARDWARE_TYPE_8192CE(rtlhal)) { | ||
379 | rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & | ||
380 | 0xFFFFFFFF); | ||
381 | rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & | ||
382 | 0xFFFFFFFF); | ||
383 | rtlpci->irq_enabled = true; | ||
384 | } else { | ||
385 | rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] & | ||
386 | 0xFFFFFFFF); | ||
387 | rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] & | ||
388 | 0xFFFFFFFF); | ||
389 | rtlusb->irq_enabled = true; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | void rtl92c_init_interrupt(struct ieee80211_hw *hw) | ||
394 | { | ||
395 | rtl92c_enable_interrupt(hw); | ||
396 | } | ||
397 | |||
398 | void rtl92c_disable_interrupt(struct ieee80211_hw *hw) | ||
399 | { | ||
400 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
401 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
402 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
403 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); | ||
404 | |||
405 | rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); | ||
406 | rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); | ||
407 | if (IS_HARDWARE_TYPE_8192CE(rtlhal)) | ||
408 | rtlpci->irq_enabled = false; | ||
409 | else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) | ||
410 | rtlusb->irq_enabled = false; | ||
411 | } | ||
412 | |||
413 | void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) | ||
414 | { | ||
415 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
416 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
417 | u32 u4b_ac_param; | ||
418 | |||
419 | rtl92c_dm_init_edca_turbo(hw); | ||
420 | u4b_ac_param = (u32) mac->ac[aci].aifs; | ||
421 | u4b_ac_param |= | ||
422 | ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) << | ||
423 | AC_PARAM_ECW_MIN_OFFSET; | ||
424 | u4b_ac_param |= | ||
425 | ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) << | ||
426 | AC_PARAM_ECW_MAX_OFFSET; | ||
427 | u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) << | ||
428 | AC_PARAM_TXOP_OFFSET; | ||
429 | RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD, | ||
430 | ("queue:%x, ac_param:%x\n", aci, u4b_ac_param)); | ||
431 | switch (aci) { | ||
432 | case AC1_BK: | ||
433 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); | ||
434 | break; | ||
435 | case AC0_BE: | ||
436 | rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); | ||
437 | break; | ||
438 | case AC2_VI: | ||
439 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); | ||
440 | break; | ||
441 | case AC3_VO: | ||
442 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); | ||
443 | break; | ||
444 | default: | ||
445 | RT_ASSERT(false, ("invalid aci: %d !\n", aci)); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /*------------------------------------------------------------------------- | ||
451 | * HW MAC Address | ||
452 | *-------------------------------------------------------------------------*/ | ||
453 | void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr) | ||
454 | { | ||
455 | u32 i; | ||
456 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
457 | |||
458 | for (i = 0 ; i < ETH_ALEN ; i++) | ||
459 | rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i)); | ||
460 | |||
461 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("MAC Address: %02X-%02X-%02X-" | ||
462 | "%02X-%02X-%02X\n", | ||
463 | rtl_read_byte(rtlpriv, REG_MACID), | ||
464 | rtl_read_byte(rtlpriv, REG_MACID+1), | ||
465 | rtl_read_byte(rtlpriv, REG_MACID+2), | ||
466 | rtl_read_byte(rtlpriv, REG_MACID+3), | ||
467 | rtl_read_byte(rtlpriv, REG_MACID+4), | ||
468 | rtl_read_byte(rtlpriv, REG_MACID+5))); | ||
469 | } | ||
470 | |||
471 | void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) | ||
472 | { | ||
473 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
474 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); | ||
475 | } | ||
476 | |||
477 | int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | ||
478 | { | ||
479 | u8 value; | ||
480 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
481 | |||
482 | switch (type) { | ||
483 | case NL80211_IFTYPE_UNSPECIFIED: | ||
484 | value = NT_NO_LINK; | ||
485 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
486 | ("Set Network type to NO LINK!\n")); | ||
487 | break; | ||
488 | case NL80211_IFTYPE_ADHOC: | ||
489 | value = NT_LINK_AD_HOC; | ||
490 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
491 | ("Set Network type to Ad Hoc!\n")); | ||
492 | break; | ||
493 | case NL80211_IFTYPE_STATION: | ||
494 | value = NT_LINK_AP; | ||
495 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
496 | ("Set Network type to STA!\n")); | ||
497 | break; | ||
498 | case NL80211_IFTYPE_AP: | ||
499 | value = NT_AS_AP; | ||
500 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
501 | ("Set Network type to AP!\n")); | ||
502 | break; | ||
503 | default: | ||
504 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
505 | ("Network type %d not support!\n", type)); | ||
506 | return -EOPNOTSUPP; | ||
507 | } | ||
508 | rtl_write_byte(rtlpriv, (REG_CR + 2), value); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | void rtl92c_init_network_type(struct ieee80211_hw *hw) | ||
513 | { | ||
514 | rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED); | ||
515 | } | ||
516 | |||
517 | void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw) | ||
518 | { | ||
519 | u16 value16; | ||
520 | u32 value32; | ||
521 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
522 | |||
523 | /* Response Rate Set */ | ||
524 | value32 = rtl_read_dword(rtlpriv, REG_RRSR); | ||
525 | value32 &= ~RATE_BITMAP_ALL; | ||
526 | value32 |= RATE_RRSR_CCK_ONLY_1M; | ||
527 | rtl_write_dword(rtlpriv, REG_RRSR, value32); | ||
528 | /* SIFS (used in NAV) */ | ||
529 | value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); | ||
530 | rtl_write_word(rtlpriv, REG_SPEC_SIFS, value16); | ||
531 | /* Retry Limit */ | ||
532 | value16 = _LRL(0x30) | _SRL(0x30); | ||
533 | rtl_write_dword(rtlpriv, REG_RL, value16); | ||
534 | } | ||
535 | |||
536 | void rtl92c_init_rate_fallback(struct ieee80211_hw *hw) | ||
537 | { | ||
538 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
539 | |||
540 | /* Set Data Auto Rate Fallback Retry Count register. */ | ||
541 | rtl_write_dword(rtlpriv, REG_DARFRC, 0x00000000); | ||
542 | rtl_write_dword(rtlpriv, REG_DARFRC+4, 0x10080404); | ||
543 | rtl_write_dword(rtlpriv, REG_RARFRC, 0x04030201); | ||
544 | rtl_write_dword(rtlpriv, REG_RARFRC+4, 0x08070605); | ||
545 | } | ||
546 | |||
547 | static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs, | ||
548 | u8 ctx_sifs) | ||
549 | { | ||
550 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
551 | |||
552 | rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs); | ||
553 | rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs); | ||
554 | } | ||
555 | |||
556 | static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs, | ||
557 | u8 ctx_sifs) | ||
558 | { | ||
559 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
560 | |||
561 | rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs); | ||
562 | rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs); | ||
563 | } | ||
564 | |||
565 | void rtl92c_init_edca_param(struct ieee80211_hw *hw, | ||
566 | u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs) | ||
567 | { | ||
568 | /* sequence: VO, VI, BE, BK ==> the same as 92C hardware design. | ||
569 | * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function. | ||
570 | */ | ||
571 | u32 value; | ||
572 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
573 | |||
574 | value = (u32)aifs; | ||
575 | value |= ((u32)cw_min & 0xF) << 8; | ||
576 | value |= ((u32)cw_max & 0xF) << 12; | ||
577 | value |= (u32)txop << 16; | ||
578 | /* 92C hardware register sequence is the same as queue number. */ | ||
579 | rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value); | ||
580 | } | ||
581 | |||
582 | void rtl92c_init_edca(struct ieee80211_hw *hw) | ||
583 | { | ||
584 | u16 value16; | ||
585 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
586 | |||
587 | /* disable EDCCA count down, to reduce collison and retry */ | ||
588 | value16 = rtl_read_word(rtlpriv, REG_RD_CTRL); | ||
589 | value16 |= DIS_EDCA_CNT_DWN; | ||
590 | rtl_write_word(rtlpriv, REG_RD_CTRL, value16); | ||
591 | /* Update SIFS timing. ?????????? | ||
592 | * pHalData->SifsTime = 0x0e0e0a0a; */ | ||
593 | rtl92c_set_cck_sifs(hw, 0xa, 0xa); | ||
594 | rtl92c_set_ofdm_sifs(hw, 0xe, 0xe); | ||
595 | /* Set CCK/OFDM SIFS to be 10us. */ | ||
596 | rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a); | ||
597 | rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010); | ||
598 | rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204); | ||
599 | rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004); | ||
600 | /* TXOP */ | ||
601 | rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B); | ||
602 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F); | ||
603 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324); | ||
604 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226); | ||
605 | /* PIFS */ | ||
606 | rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); | ||
607 | /* AGGR BREAK TIME Register */ | ||
608 | rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); | ||
609 | rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); | ||
610 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02); | ||
611 | rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02); | ||
612 | } | ||
613 | |||
614 | void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw) | ||
615 | { | ||
616 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
617 | |||
618 | rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631); | ||
619 | rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); | ||
620 | /* init AMPDU aggregation number, tuning for Tx's TP, */ | ||
621 | rtl_write_word(rtlpriv, 0x4CA, 0x0708); | ||
622 | } | ||
623 | |||
624 | void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode) | ||
625 | { | ||
626 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
627 | |||
628 | rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF); | ||
629 | } | ||
630 | |||
631 | void rtl92c_init_rdg_setting(struct ieee80211_hw *hw) | ||
632 | { | ||
633 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
634 | |||
635 | rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF); | ||
636 | rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); | ||
637 | rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); | ||
638 | } | ||
639 | |||
640 | void rtl92c_init_retry_function(struct ieee80211_hw *hw) | ||
641 | { | ||
642 | u8 value8; | ||
643 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
644 | |||
645 | value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL); | ||
646 | value8 |= EN_AMPDU_RTY_NEW; | ||
647 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8); | ||
648 | /* Set ACK timeout */ | ||
649 | rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); | ||
650 | } | ||
651 | |||
652 | void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw, | ||
653 | enum version_8192c version) | ||
654 | { | ||
655 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
656 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
657 | |||
658 | rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */ | ||
659 | rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/ | ||
660 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); | ||
661 | if (IS_NORMAL_CHIP(rtlhal->version)) | ||
662 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); | ||
663 | else | ||
664 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); | ||
665 | } | ||
666 | |||
667 | void rtl92c_disable_fast_edca(struct ieee80211_hw *hw) | ||
668 | { | ||
669 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
670 | |||
671 | rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0); | ||
672 | } | ||
673 | |||
674 | void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T) | ||
675 | { | ||
676 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
677 | u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T; | ||
678 | |||
679 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value); | ||
680 | } | ||
681 | |||
682 | u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw) | ||
683 | { | ||
684 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
685 | |||
686 | return rtl_read_word(rtlpriv, REG_RXFLTMAP0); | ||
687 | } | ||
688 | |||
689 | void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter) | ||
690 | { | ||
691 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
692 | |||
693 | rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter); | ||
694 | } | ||
695 | |||
696 | u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw) | ||
697 | { | ||
698 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
699 | |||
700 | return rtl_read_word(rtlpriv, REG_RXFLTMAP1); | ||
701 | } | ||
702 | |||
703 | void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter) | ||
704 | { | ||
705 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
706 | |||
707 | rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter); | ||
708 | } | ||
709 | |||
710 | u16 rtl92c_get_data_filter(struct ieee80211_hw *hw) | ||
711 | { | ||
712 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
713 | |||
714 | return rtl_read_word(rtlpriv, REG_RXFLTMAP2); | ||
715 | } | ||
716 | |||
717 | void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter) | ||
718 | { | ||
719 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
720 | |||
721 | rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter); | ||
722 | } | ||
723 | /*==============================================================*/ | ||
724 | |||
725 | static u8 _rtl92c_query_rxpwrpercentage(char antpower) | ||
726 | { | ||
727 | if ((antpower <= -100) || (antpower >= 20)) | ||
728 | return 0; | ||
729 | else if (antpower >= 0) | ||
730 | return 100; | ||
731 | else | ||
732 | return 100 + antpower; | ||
733 | } | ||
734 | |||
735 | static u8 _rtl92c_evm_db_to_percentage(char value) | ||
736 | { | ||
737 | char ret_val; | ||
738 | |||
739 | ret_val = value; | ||
740 | if (ret_val >= 0) | ||
741 | ret_val = 0; | ||
742 | if (ret_val <= -33) | ||
743 | ret_val = -33; | ||
744 | ret_val = 0 - ret_val; | ||
745 | ret_val *= 3; | ||
746 | if (ret_val == 99) | ||
747 | ret_val = 100; | ||
748 | return ret_val; | ||
749 | } | ||
750 | |||
751 | static long _rtl92c_translate_todbm(struct ieee80211_hw *hw, | ||
752 | u8 signal_strength_index) | ||
753 | { | ||
754 | long signal_power; | ||
755 | |||
756 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
757 | signal_power -= 95; | ||
758 | return signal_power; | ||
759 | } | ||
760 | |||
761 | static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, | ||
762 | long currsig) | ||
763 | { | ||
764 | long retsig; | ||
765 | |||
766 | if (currsig >= 61 && currsig <= 100) | ||
767 | retsig = 90 + ((currsig - 60) / 4); | ||
768 | else if (currsig >= 41 && currsig <= 60) | ||
769 | retsig = 78 + ((currsig - 40) / 2); | ||
770 | else if (currsig >= 31 && currsig <= 40) | ||
771 | retsig = 66 + (currsig - 30); | ||
772 | else if (currsig >= 21 && currsig <= 30) | ||
773 | retsig = 54 + (currsig - 20); | ||
774 | else if (currsig >= 5 && currsig <= 20) | ||
775 | retsig = 42 + (((currsig - 5) * 2) / 3); | ||
776 | else if (currsig == 4) | ||
777 | retsig = 36; | ||
778 | else if (currsig == 3) | ||
779 | retsig = 27; | ||
780 | else if (currsig == 2) | ||
781 | retsig = 18; | ||
782 | else if (currsig == 1) | ||
783 | retsig = 9; | ||
784 | else | ||
785 | retsig = currsig; | ||
786 | return retsig; | ||
787 | } | ||
788 | |||
789 | static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | ||
790 | struct rtl_stats *pstats, | ||
791 | struct rx_desc_92c *pdesc, | ||
792 | struct rx_fwinfo_92c *p_drvinfo, | ||
793 | bool packet_match_bssid, | ||
794 | bool packet_toself, | ||
795 | bool packet_beacon) | ||
796 | { | ||
797 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
798 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
799 | struct phy_sts_cck_8192s_t *cck_buf; | ||
800 | s8 rx_pwr_all = 0, rx_pwr[4]; | ||
801 | u8 rf_rx_num = 0, evm, pwdb_all; | ||
802 | u8 i, max_spatial_stream; | ||
803 | u32 rssi, total_rssi = 0; | ||
804 | bool in_powersavemode = false; | ||
805 | bool is_cck_rate; | ||
806 | |||
807 | is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); | ||
808 | pstats->packet_matchbssid = packet_match_bssid; | ||
809 | pstats->packet_toself = packet_toself; | ||
810 | pstats->is_cck = is_cck_rate; | ||
811 | pstats->packet_beacon = packet_beacon; | ||
812 | pstats->is_cck = is_cck_rate; | ||
813 | pstats->RX_SIGQ[0] = -1; | ||
814 | pstats->RX_SIGQ[1] = -1; | ||
815 | if (is_cck_rate) { | ||
816 | u8 report, cck_highpwr; | ||
817 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | ||
818 | if (!in_powersavemode) | ||
819 | cck_highpwr = rtlphy->cck_high_power; | ||
820 | else | ||
821 | cck_highpwr = false; | ||
822 | if (!cck_highpwr) { | ||
823 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
824 | report = cck_buf->cck_agc_rpt & 0xc0; | ||
825 | report = report >> 6; | ||
826 | switch (report) { | ||
827 | case 0x3: | ||
828 | rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); | ||
829 | break; | ||
830 | case 0x2: | ||
831 | rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); | ||
832 | break; | ||
833 | case 0x1: | ||
834 | rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); | ||
835 | break; | ||
836 | case 0x0: | ||
837 | rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); | ||
838 | break; | ||
839 | } | ||
840 | } else { | ||
841 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
842 | report = p_drvinfo->cfosho[0] & 0x60; | ||
843 | report = report >> 5; | ||
844 | switch (report) { | ||
845 | case 0x3: | ||
846 | rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); | ||
847 | break; | ||
848 | case 0x2: | ||
849 | rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); | ||
850 | break; | ||
851 | case 0x1: | ||
852 | rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); | ||
853 | break; | ||
854 | case 0x0: | ||
855 | rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); | ||
856 | break; | ||
857 | } | ||
858 | } | ||
859 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | ||
860 | pstats->rx_pwdb_all = pwdb_all; | ||
861 | pstats->recvsignalpower = rx_pwr_all; | ||
862 | if (packet_match_bssid) { | ||
863 | u8 sq; | ||
864 | if (pstats->rx_pwdb_all > 40) | ||
865 | sq = 100; | ||
866 | else { | ||
867 | sq = cck_buf->sq_rpt; | ||
868 | if (sq > 64) | ||
869 | sq = 0; | ||
870 | else if (sq < 20) | ||
871 | sq = 100; | ||
872 | else | ||
873 | sq = ((64 - sq) * 100) / 44; | ||
874 | } | ||
875 | pstats->signalquality = sq; | ||
876 | pstats->RX_SIGQ[0] = sq; | ||
877 | pstats->RX_SIGQ[1] = -1; | ||
878 | } | ||
879 | } else { | ||
880 | rtlpriv->dm.rfpath_rxenable[0] = | ||
881 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
882 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | ||
883 | if (rtlpriv->dm.rfpath_rxenable[i]) | ||
884 | rf_rx_num++; | ||
885 | rx_pwr[i] = | ||
886 | ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; | ||
887 | rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); | ||
888 | total_rssi += rssi; | ||
889 | rtlpriv->stats.rx_snr_db[i] = | ||
890 | (long)(p_drvinfo->rxsnr[i] / 2); | ||
891 | |||
892 | if (packet_match_bssid) | ||
893 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; | ||
894 | } | ||
895 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | ||
896 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | ||
897 | pstats->rx_pwdb_all = pwdb_all; | ||
898 | pstats->rxpower = rx_pwr_all; | ||
899 | pstats->recvsignalpower = rx_pwr_all; | ||
900 | if (GET_RX_DESC_RX_MCS(pdesc) && | ||
901 | GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 && | ||
902 | GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15) | ||
903 | max_spatial_stream = 2; | ||
904 | else | ||
905 | max_spatial_stream = 1; | ||
906 | for (i = 0; i < max_spatial_stream; i++) { | ||
907 | evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); | ||
908 | if (packet_match_bssid) { | ||
909 | if (i == 0) | ||
910 | pstats->signalquality = | ||
911 | (u8) (evm & 0xff); | ||
912 | pstats->RX_SIGQ[i] = | ||
913 | (u8) (evm & 0xff); | ||
914 | } | ||
915 | } | ||
916 | } | ||
917 | if (is_cck_rate) | ||
918 | pstats->signalstrength = | ||
919 | (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all)); | ||
920 | else if (rf_rx_num != 0) | ||
921 | pstats->signalstrength = | ||
922 | (u8) (_rtl92c_signal_scale_mapping | ||
923 | (hw, total_rssi /= rf_rx_num)); | ||
924 | } | ||
925 | |||
926 | static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw, | ||
927 | struct rtl_stats *pstats) | ||
928 | { | ||
929 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
930 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
931 | u8 rfpath; | ||
932 | u32 last_rssi, tmpval; | ||
933 | |||
934 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
935 | rtlpriv->stats.rssi_calculate_cnt++; | ||
936 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
937 | PHY_RSSI_SLID_WIN_MAX) { | ||
938 | rtlpriv->stats.ui_rssi.total_num = | ||
939 | PHY_RSSI_SLID_WIN_MAX; | ||
940 | last_rssi = | ||
941 | rtlpriv->stats.ui_rssi.elements[rtlpriv-> | ||
942 | stats.ui_rssi.index]; | ||
943 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
944 | } | ||
945 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
946 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. | ||
947 | index++] = pstats->signalstrength; | ||
948 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
949 | rtlpriv->stats.ui_rssi.index = 0; | ||
950 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
951 | rtlpriv->stats.ui_rssi.total_num; | ||
952 | rtlpriv->stats.signal_strength = | ||
953 | _rtl92c_translate_todbm(hw, (u8) tmpval); | ||
954 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
955 | } | ||
956 | if (!pstats->is_cck && pstats->packet_toself) { | ||
957 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
958 | rfpath++) { | ||
959 | if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) | ||
960 | continue; | ||
961 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
962 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
963 | pstats->rx_mimo_signalstrength[rfpath]; | ||
964 | } | ||
965 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
966 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
967 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
968 | ((rtlpriv->stats. | ||
969 | rx_rssi_percentage[rfpath] * | ||
970 | (RX_SMOOTH_FACTOR - 1)) + | ||
971 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
972 | (RX_SMOOTH_FACTOR); | ||
973 | |||
974 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
975 | rtlpriv->stats.rx_rssi_percentage[rfpath] + | ||
976 | 1; | ||
977 | } else { | ||
978 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
979 | ((rtlpriv->stats. | ||
980 | rx_rssi_percentage[rfpath] * | ||
981 | (RX_SMOOTH_FACTOR - 1)) + | ||
982 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
983 | (RX_SMOOTH_FACTOR); | ||
984 | } | ||
985 | } | ||
986 | } | ||
987 | } | ||
988 | |||
989 | static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
990 | struct rtl_stats *pstats) | ||
991 | { | ||
992 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
993 | int weighting = 0; | ||
994 | |||
995 | if (rtlpriv->stats.recv_signal_power == 0) | ||
996 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
997 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
998 | weighting = 5; | ||
999 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
1000 | weighting = (-5); | ||
1001 | rtlpriv->stats.recv_signal_power = | ||
1002 | (rtlpriv->stats.recv_signal_power * 5 + | ||
1003 | pstats->recvsignalpower + weighting) / 6; | ||
1004 | } | ||
1005 | |||
1006 | static void _rtl92c_process_pwdb(struct ieee80211_hw *hw, | ||
1007 | struct rtl_stats *pstats) | ||
1008 | { | ||
1009 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1010 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1011 | long undecorated_smoothed_pwdb = 0; | ||
1012 | |||
1013 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
1014 | return; | ||
1015 | } else { | ||
1016 | undecorated_smoothed_pwdb = | ||
1017 | rtlpriv->dm.undecorated_smoothed_pwdb; | ||
1018 | } | ||
1019 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
1020 | if (undecorated_smoothed_pwdb < 0) | ||
1021 | undecorated_smoothed_pwdb = pstats->rx_pwdb_all; | ||
1022 | if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { | ||
1023 | undecorated_smoothed_pwdb = | ||
1024 | (((undecorated_smoothed_pwdb) * | ||
1025 | (RX_SMOOTH_FACTOR - 1)) + | ||
1026 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
1027 | undecorated_smoothed_pwdb = undecorated_smoothed_pwdb | ||
1028 | + 1; | ||
1029 | } else { | ||
1030 | undecorated_smoothed_pwdb = | ||
1031 | (((undecorated_smoothed_pwdb) * | ||
1032 | (RX_SMOOTH_FACTOR - 1)) + | ||
1033 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
1034 | } | ||
1035 | rtlpriv->dm.undecorated_smoothed_pwdb = | ||
1036 | undecorated_smoothed_pwdb; | ||
1037 | _rtl92c_update_rxsignalstatistics(hw, pstats); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw, | ||
1042 | struct rtl_stats *pstats) | ||
1043 | { | ||
1044 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1045 | u32 last_evm = 0, n_stream, tmpval; | ||
1046 | |||
1047 | if (pstats->signalquality != 0) { | ||
1048 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
1049 | if (rtlpriv->stats.LINK_Q.total_num++ >= | ||
1050 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
1051 | rtlpriv->stats.LINK_Q.total_num = | ||
1052 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
1053 | last_evm = | ||
1054 | rtlpriv->stats.LINK_Q.elements | ||
1055 | [rtlpriv->stats.LINK_Q.index]; | ||
1056 | rtlpriv->stats.LINK_Q.total_val -= | ||
1057 | last_evm; | ||
1058 | } | ||
1059 | rtlpriv->stats.LINK_Q.total_val += | ||
1060 | pstats->signalquality; | ||
1061 | rtlpriv->stats.LINK_Q.elements | ||
1062 | [rtlpriv->stats.LINK_Q.index++] = | ||
1063 | pstats->signalquality; | ||
1064 | if (rtlpriv->stats.LINK_Q.index >= | ||
1065 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
1066 | rtlpriv->stats.LINK_Q.index = 0; | ||
1067 | tmpval = rtlpriv->stats.LINK_Q.total_val / | ||
1068 | rtlpriv->stats.LINK_Q.total_num; | ||
1069 | rtlpriv->stats.signal_quality = tmpval; | ||
1070 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
1071 | for (n_stream = 0; n_stream < 2; | ||
1072 | n_stream++) { | ||
1073 | if (pstats->RX_SIGQ[n_stream] != -1) { | ||
1074 | if (!rtlpriv->stats.RX_EVM[n_stream]) { | ||
1075 | rtlpriv->stats.RX_EVM[n_stream] | ||
1076 | = pstats->RX_SIGQ[n_stream]; | ||
1077 | } | ||
1078 | rtlpriv->stats.RX_EVM[n_stream] = | ||
1079 | ((rtlpriv->stats.RX_EVM | ||
1080 | [n_stream] * | ||
1081 | (RX_SMOOTH_FACTOR - 1)) + | ||
1082 | (pstats->RX_SIGQ | ||
1083 | [n_stream] * 1)) / | ||
1084 | (RX_SMOOTH_FACTOR); | ||
1085 | } | ||
1086 | } | ||
1087 | } | ||
1088 | } else { | ||
1089 | ; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw, | ||
1094 | u8 *buffer, | ||
1095 | struct rtl_stats *pcurrent_stats) | ||
1096 | { | ||
1097 | if (!pcurrent_stats->packet_matchbssid && | ||
1098 | !pcurrent_stats->packet_beacon) | ||
1099 | return; | ||
1100 | _rtl92c_process_ui_rssi(hw, pcurrent_stats); | ||
1101 | _rtl92c_process_pwdb(hw, pcurrent_stats); | ||
1102 | _rtl92c_process_LINK_Q(hw, pcurrent_stats); | ||
1103 | } | ||
1104 | |||
1105 | void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, | ||
1106 | struct sk_buff *skb, | ||
1107 | struct rtl_stats *pstats, | ||
1108 | struct rx_desc_92c *pdesc, | ||
1109 | struct rx_fwinfo_92c *p_drvinfo) | ||
1110 | { | ||
1111 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1112 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1113 | struct ieee80211_hdr *hdr; | ||
1114 | u8 *tmp_buf; | ||
1115 | u8 *praddr; | ||
1116 | u8 *psaddr; | ||
1117 | __le16 fc; | ||
1118 | u16 type, cpu_fc; | ||
1119 | bool packet_matchbssid, packet_toself, packet_beacon; | ||
1120 | |||
1121 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; | ||
1122 | hdr = (struct ieee80211_hdr *)tmp_buf; | ||
1123 | fc = hdr->frame_control; | ||
1124 | cpu_fc = le16_to_cpu(fc); | ||
1125 | type = WLAN_FC_GET_TYPE(fc); | ||
1126 | praddr = hdr->addr1; | ||
1127 | psaddr = hdr->addr2; | ||
1128 | packet_matchbssid = | ||
1129 | ((IEEE80211_FTYPE_CTL != type) && | ||
1130 | (!compare_ether_addr(mac->bssid, | ||
1131 | (cpu_fc & IEEE80211_FCTL_TODS) ? | ||
1132 | hdr->addr1 : (cpu_fc & IEEE80211_FCTL_FROMDS) ? | ||
1133 | hdr->addr2 : hdr->addr3)) && | ||
1134 | (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); | ||
1135 | |||
1136 | packet_toself = packet_matchbssid && | ||
1137 | (!compare_ether_addr(praddr, rtlefuse->dev_addr)); | ||
1138 | if (ieee80211_is_beacon(fc)) | ||
1139 | packet_beacon = true; | ||
1140 | _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, | ||
1141 | packet_matchbssid, packet_toself, | ||
1142 | packet_beacon); | ||
1143 | _rtl92c_process_phyinfo(hw, tmp_buf, pstats); | ||
1144 | } | ||