blob: e14f743673969a21effd070b157f5b1a5db2ef6f [file] [log] [blame]
Larry Finger0c817332010-12-08 11:12:31 -06001/******************************************************************************
2 *
3 * Copyright(c) 2009-2010 Realtek Corporation.
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
30#include "../wifi.h"
31#include "../pci.h"
32#include "../base.h"
John W. Linville5c405b52010-12-16 15:43:36 -050033#include "reg.h"
34#include "def.h"
35#include "phy.h"
36#include "trx.h"
37#include "led.h"
Larry Finger0c817332010-12-08 11:12:31 -060038
Larry Finger17c9ac62011-02-19 16:29:57 -060039static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc,
Larry Finger0c817332010-12-08 11:12:31 -060040 unsigned int
41 skb_queue)
42{
43 enum rtl_desc_qsel qsel;
44
45 if (unlikely(ieee80211_is_beacon(fc))) {
46 qsel = QSLT_BEACON;
47 return qsel;
48 }
49
50 if (ieee80211_is_mgmt(fc)) {
51 qsel = QSLT_MGNT;
52 return qsel;
53 }
54
55 switch (skb_queue) {
56 case VO_QUEUE:
57 qsel = QSLT_VO;
58 break;
59 case VI_QUEUE:
60 qsel = QSLT_VI;
61 break;
62 case BE_QUEUE:
63 qsel = QSLT_BE;
64 break;
65 case BK_QUEUE:
66 qsel = QSLT_BK;
67 break;
68 default:
69 qsel = QSLT_BE;
70 RT_ASSERT(false, ("BE queue, skb_queue:%d,"
71 " set qsel = 0x%X\n", skb_queue, QSLT_BE));
72 break;
73 }
74 return qsel;
75}
76
77static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
78{
79 int rate_idx;
80
81 if (first_ampdu) {
82 if (false == isht) {
83 switch (desc_rate) {
84 case DESC92C_RATE1M:
85 rate_idx = 0;
86 break;
87 case DESC92C_RATE2M:
88 rate_idx = 1;
89 break;
90 case DESC92C_RATE5_5M:
91 rate_idx = 2;
92 break;
93 case DESC92C_RATE11M:
94 rate_idx = 3;
95 break;
96 case DESC92C_RATE6M:
97 rate_idx = 4;
98 break;
99 case DESC92C_RATE9M:
100 rate_idx = 5;
101 break;
102 case DESC92C_RATE12M:
103 rate_idx = 6;
104 break;
105 case DESC92C_RATE18M:
106 rate_idx = 7;
107 break;
108 case DESC92C_RATE24M:
109 rate_idx = 8;
110 break;
111 case DESC92C_RATE36M:
112 rate_idx = 9;
113 break;
114 case DESC92C_RATE48M:
115 rate_idx = 10;
116 break;
117 case DESC92C_RATE54M:
118 rate_idx = 11;
119 break;
120 default:
121 rate_idx = 0;
122 break;
123 }
124 } else {
125 rate_idx = 11;
126 }
127
128 return rate_idx;
129 }
130
131 switch (desc_rate) {
132 case DESC92C_RATE1M:
133 rate_idx = 0;
134 break;
135 case DESC92C_RATE2M:
136 rate_idx = 1;
137 break;
138 case DESC92C_RATE5_5M:
139 rate_idx = 2;
140 break;
141 case DESC92C_RATE11M:
142 rate_idx = 3;
143 break;
144 case DESC92C_RATE6M:
145 rate_idx = 4;
146 break;
147 case DESC92C_RATE9M:
148 rate_idx = 5;
149 break;
150 case DESC92C_RATE12M:
151 rate_idx = 6;
152 break;
153 case DESC92C_RATE18M:
154 rate_idx = 7;
155 break;
156 case DESC92C_RATE24M:
157 rate_idx = 8;
158 break;
159 case DESC92C_RATE36M:
160 rate_idx = 9;
161 break;
162 case DESC92C_RATE48M:
163 rate_idx = 10;
164 break;
165 case DESC92C_RATE54M:
166 rate_idx = 11;
167 break;
168 default:
169 rate_idx = 11;
170 break;
171 }
172 return rate_idx;
173}
174
175static u8 _rtl92c_query_rxpwrpercentage(char antpower)
176{
177 if ((antpower <= -100) || (antpower >= 20))
178 return 0;
179 else if (antpower >= 0)
180 return 100;
181 else
182 return 100 + antpower;
183}
184
185static u8 _rtl92c_evm_db_to_percentage(char value)
186{
187 char ret_val;
188 ret_val = value;
189
190 if (ret_val >= 0)
191 ret_val = 0;
192
193 if (ret_val <= -33)
194 ret_val = -33;
195
196 ret_val = 0 - ret_val;
197 ret_val *= 3;
198
199 if (ret_val == 99)
200 ret_val = 100;
201
202 return ret_val;
203}
204
205static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw,
206 u8 signal_strength_index)
207{
208 long signal_power;
209
210 signal_power = (long)((signal_strength_index + 1) >> 1);
211 signal_power -= 95;
212 return signal_power;
213}
214
215static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw,
216 long currsig)
217{
218 long retsig;
219
220 if (currsig >= 61 && currsig <= 100)
221 retsig = 90 + ((currsig - 60) / 4);
222 else if (currsig >= 41 && currsig <= 60)
223 retsig = 78 + ((currsig - 40) / 2);
224 else if (currsig >= 31 && currsig <= 40)
225 retsig = 66 + (currsig - 30);
226 else if (currsig >= 21 && currsig <= 30)
227 retsig = 54 + (currsig - 20);
228 else if (currsig >= 5 && currsig <= 20)
229 retsig = 42 + (((currsig - 5) * 2) / 3);
230 else if (currsig == 4)
231 retsig = 36;
232 else if (currsig == 3)
233 retsig = 27;
234 else if (currsig == 2)
235 retsig = 18;
236 else if (currsig == 1)
237 retsig = 9;
238 else
239 retsig = currsig;
240
241 return retsig;
242}
243
244static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
245 struct rtl_stats *pstats,
246 struct rx_desc_92c *pdesc,
247 struct rx_fwinfo_92c *p_drvinfo,
Larry Finger7ea47242011-02-19 16:28:57 -0600248 bool packet_match_bssid,
249 bool packet_toself,
250 bool packet_beacon)
Larry Finger0c817332010-12-08 11:12:31 -0600251{
252 struct rtl_priv *rtlpriv = rtl_priv(hw);
253 struct phy_sts_cck_8192s_t *cck_buf;
254 s8 rx_pwr_all, rx_pwr[4];
255 u8 rf_rx_num, evm, pwdb_all;
256 u8 i, max_spatial_stream;
257 u32 rssi, total_rssi;
258 bool is_cck_rate;
259
260 is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
Larry Finger7ea47242011-02-19 16:28:57 -0600261 pstats->packet_matchbssid = packet_match_bssid;
262 pstats->packet_toself = packet_toself;
263 pstats->is_cck = is_cck_rate;
264 pstats->packet_beacon = packet_beacon;
265 pstats->is_cck = is_cck_rate;
Larry Finger0c817332010-12-08 11:12:31 -0600266 pstats->rx_mimo_signalquality[0] = -1;
267 pstats->rx_mimo_signalquality[1] = -1;
268
269 if (is_cck_rate) {
270 u8 report, cck_highpwr;
271 cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
272
273 cck_highpwr = (u8) rtl_get_bbreg(hw,
274 RFPGA0_XA_HSSIPARAMETER2,
275 BIT(9));
276 if (!cck_highpwr) {
277 u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
278 report = cck_buf->cck_agc_rpt & 0xc0;
279 report = report >> 6;
280 switch (report) {
281 case 0x3:
282 rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
283 break;
284 case 0x2:
285 rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
286 break;
287 case 0x1:
288 rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
289 break;
290 case 0x0:
291 rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
292 break;
293 }
294 } else {
295 u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
296 report = p_drvinfo->cfosho[0] & 0x60;
297 report = report >> 5;
298 switch (report) {
299 case 0x3:
300 rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
301 break;
302 case 0x2:
303 rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
304 break;
305 case 0x1:
306 rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
307 break;
308 case 0x0:
309 rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
310 break;
311 }
312 }
313
314 pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
315 pstats->rx_pwdb_all = pwdb_all;
316 pstats->recvsignalpower = rx_pwr_all;
317
Larry Finger7ea47242011-02-19 16:28:57 -0600318 if (packet_match_bssid) {
Larry Finger0c817332010-12-08 11:12:31 -0600319 u8 sq;
320 if (pstats->rx_pwdb_all > 40)
321 sq = 100;
322 else {
323 sq = cck_buf->sq_rpt;
324 if (sq > 64)
325 sq = 0;
326 else if (sq < 20)
327 sq = 100;
328 else
329 sq = ((64 - sq) * 100) / 44;
330 }
331
332 pstats->signalquality = sq;
333 pstats->rx_mimo_signalquality[0] = sq;
334 pstats->rx_mimo_signalquality[1] = -1;
335 }
336 } else {
Larry Finger7ea47242011-02-19 16:28:57 -0600337 rtlpriv->dm.rfpath_rxenable[0] =
338 rtlpriv->dm.rfpath_rxenable[1] = true;
Larry Finger0c817332010-12-08 11:12:31 -0600339 for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
Larry Finger7ea47242011-02-19 16:28:57 -0600340 if (rtlpriv->dm.rfpath_rxenable[i])
Larry Finger0c817332010-12-08 11:12:31 -0600341 rf_rx_num++;
342
343 rx_pwr[i] =
344 ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
345 rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
346 total_rssi += rssi;
347 rtlpriv->stats.rx_snr_db[i] =
348 (long)(p_drvinfo->rxsnr[i] / 2);
349
Larry Finger7ea47242011-02-19 16:28:57 -0600350 if (packet_match_bssid)
Larry Finger0c817332010-12-08 11:12:31 -0600351 pstats->rx_mimo_signalstrength[i] = (u8) rssi;
352 }
353
354 rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
355 pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
356 pstats->rx_pwdb_all = pwdb_all;
357 pstats->rxpower = rx_pwr_all;
358 pstats->recvsignalpower = rx_pwr_all;
359
360 if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 &&
361 pdesc->rxmcs <= DESC92C_RATEMCS15)
362 max_spatial_stream = 2;
363 else
364 max_spatial_stream = 1;
365
366 for (i = 0; i < max_spatial_stream; i++) {
367 evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
368
Larry Finger7ea47242011-02-19 16:28:57 -0600369 if (packet_match_bssid) {
Larry Finger0c817332010-12-08 11:12:31 -0600370 if (i == 0)
371 pstats->signalquality =
372 (u8) (evm & 0xff);
373 pstats->rx_mimo_signalquality[i] =
374 (u8) (evm & 0xff);
375 }
376 }
377 }
378
379 if (is_cck_rate)
380 pstats->signalstrength =
381 (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all));
382 else if (rf_rx_num != 0)
383 pstats->signalstrength =
384 (u8) (_rtl92ce_signal_scale_mapping
385 (hw, total_rssi /= rf_rx_num));
386}
387
388static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
389 struct rtl_stats *pstats)
390{
391 struct rtl_priv *rtlpriv = rtl_priv(hw);
392 struct rtl_phy *rtlphy = &(rtlpriv->phy);
393 u8 rfpath;
394 u32 last_rssi, tmpval;
395
Larry Finger7ea47242011-02-19 16:28:57 -0600396 if (pstats->packet_toself || pstats->packet_beacon) {
Larry Finger0c817332010-12-08 11:12:31 -0600397 rtlpriv->stats.rssi_calculate_cnt++;
398
399 if (rtlpriv->stats.ui_rssi.total_num++ >=
400 PHY_RSSI_SLID_WIN_MAX) {
401 rtlpriv->stats.ui_rssi.total_num =
402 PHY_RSSI_SLID_WIN_MAX;
403 last_rssi =
404 rtlpriv->stats.ui_rssi.elements[rtlpriv->
405 stats.ui_rssi.index];
406 rtlpriv->stats.ui_rssi.total_val -= last_rssi;
407 }
408
409 rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
410 rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
411 index++] =
412 pstats->signalstrength;
413
414 if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
415 rtlpriv->stats.ui_rssi.index = 0;
416
417 tmpval = rtlpriv->stats.ui_rssi.total_val /
418 rtlpriv->stats.ui_rssi.total_num;
419 rtlpriv->stats.signal_strength =
420 _rtl92ce_translate_todbm(hw, (u8) tmpval);
421 pstats->rssi = rtlpriv->stats.signal_strength;
422 }
423
Larry Finger7ea47242011-02-19 16:28:57 -0600424 if (!pstats->is_cck && pstats->packet_toself) {
Larry Finger0c817332010-12-08 11:12:31 -0600425 for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
426 rfpath++) {
427
428 if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
429 continue;
430
431 if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
432 rtlpriv->stats.rx_rssi_percentage[rfpath] =
433 pstats->rx_mimo_signalstrength[rfpath];
434
435 }
436
437 if (pstats->rx_mimo_signalstrength[rfpath] >
438 rtlpriv->stats.rx_rssi_percentage[rfpath]) {
439 rtlpriv->stats.rx_rssi_percentage[rfpath] =
440 ((rtlpriv->stats.
441 rx_rssi_percentage[rfpath] *
442 (RX_SMOOTH_FACTOR - 1)) +
443 (pstats->rx_mimo_signalstrength[rfpath])) /
444 (RX_SMOOTH_FACTOR);
445
446 rtlpriv->stats.rx_rssi_percentage[rfpath] =
447 rtlpriv->stats.rx_rssi_percentage[rfpath] +
448 1;
449 } else {
450 rtlpriv->stats.rx_rssi_percentage[rfpath] =
451 ((rtlpriv->stats.
452 rx_rssi_percentage[rfpath] *
453 (RX_SMOOTH_FACTOR - 1)) +
454 (pstats->rx_mimo_signalstrength[rfpath])) /
455 (RX_SMOOTH_FACTOR);
456 }
457
458 }
459 }
460}
461
462static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw,
463 struct rtl_stats *pstats)
464{
465 struct rtl_priv *rtlpriv = rtl_priv(hw);
466 int weighting;
467
468 if (rtlpriv->stats.recv_signal_power == 0)
469 rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
470
471 if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
472 weighting = 5;
473
474 else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
475 weighting = (-5);
476
477 rtlpriv->stats.recv_signal_power =
478 (rtlpriv->stats.recv_signal_power * 5 +
479 pstats->recvsignalpower + weighting) / 6;
480}
481
482static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
483 struct rtl_stats *pstats)
484{
485 struct rtl_priv *rtlpriv = rtl_priv(hw);
486 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
487 long undecorated_smoothed_pwdb;
488
489 if (mac->opmode == NL80211_IFTYPE_ADHOC) {
490 return;
491 } else {
492 undecorated_smoothed_pwdb =
493 rtlpriv->dm.undecorated_smoothed_pwdb;
494 }
495
Larry Finger7ea47242011-02-19 16:28:57 -0600496 if (pstats->packet_toself || pstats->packet_beacon) {
Larry Finger0c817332010-12-08 11:12:31 -0600497 if (undecorated_smoothed_pwdb < 0)
498 undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
499
500 if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
501 undecorated_smoothed_pwdb =
502 (((undecorated_smoothed_pwdb) *
503 (RX_SMOOTH_FACTOR - 1)) +
504 (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
505
506 undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
507 + 1;
508 } else {
509 undecorated_smoothed_pwdb =
510 (((undecorated_smoothed_pwdb) *
511 (RX_SMOOTH_FACTOR - 1)) +
512 (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
513 }
514
515 rtlpriv->dm.undecorated_smoothed_pwdb =
516 undecorated_smoothed_pwdb;
517 _rtl92ce_update_rxsignalstatistics(hw, pstats);
518 }
519}
520
521static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
522 struct rtl_stats *pstats)
523{
524 struct rtl_priv *rtlpriv = rtl_priv(hw);
525 u32 last_evm, n_spatialstream, tmpval;
526
527 if (pstats->signalquality != 0) {
Larry Finger7ea47242011-02-19 16:28:57 -0600528 if (pstats->packet_toself || pstats->packet_beacon) {
Larry Finger0c817332010-12-08 11:12:31 -0600529
530 if (rtlpriv->stats.ui_link_quality.total_num++ >=
531 PHY_LINKQUALITY_SLID_WIN_MAX) {
532 rtlpriv->stats.ui_link_quality.total_num =
533 PHY_LINKQUALITY_SLID_WIN_MAX;
534 last_evm =
535 rtlpriv->stats.
536 ui_link_quality.elements[rtlpriv->
537 stats.ui_link_quality.
538 index];
539 rtlpriv->stats.ui_link_quality.total_val -=
540 last_evm;
541 }
542
543 rtlpriv->stats.ui_link_quality.total_val +=
544 pstats->signalquality;
545 rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats.
546 ui_link_quality.
547 index++] =
548 pstats->signalquality;
549
550 if (rtlpriv->stats.ui_link_quality.index >=
551 PHY_LINKQUALITY_SLID_WIN_MAX)
552 rtlpriv->stats.ui_link_quality.index = 0;
553
554 tmpval = rtlpriv->stats.ui_link_quality.total_val /
555 rtlpriv->stats.ui_link_quality.total_num;
556 rtlpriv->stats.signal_quality = tmpval;
557
558 rtlpriv->stats.last_sigstrength_inpercent = tmpval;
559
560 for (n_spatialstream = 0; n_spatialstream < 2;
561 n_spatialstream++) {
562 if (pstats->
563 rx_mimo_signalquality[n_spatialstream] !=
564 -1) {
565 if (rtlpriv->stats.
566 rx_evm_percentage[n_spatialstream]
567 == 0) {
568 rtlpriv->stats.
569 rx_evm_percentage
570 [n_spatialstream] =
571 pstats->rx_mimo_signalquality
572 [n_spatialstream];
573 }
574
575 rtlpriv->stats.
576 rx_evm_percentage[n_spatialstream] =
577 ((rtlpriv->
578 stats.rx_evm_percentage
579 [n_spatialstream] *
580 (RX_SMOOTH_FACTOR - 1)) +
581 (pstats->
582 rx_mimo_signalquality
583 [n_spatialstream] * 1)) /
584 (RX_SMOOTH_FACTOR);
585 }
586 }
587 }
588 } else {
589 ;
590 }
591}
592
593static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw,
594 u8 *buffer,
595 struct rtl_stats *pcurrent_stats)
596{
597
Larry Finger7ea47242011-02-19 16:28:57 -0600598 if (!pcurrent_stats->packet_matchbssid &&
599 !pcurrent_stats->packet_beacon)
Larry Finger0c817332010-12-08 11:12:31 -0600600 return;
601
602 _rtl92ce_process_ui_rssi(hw, pcurrent_stats);
603 _rtl92ce_process_pwdb(hw, pcurrent_stats);
604 _rtl92ce_process_ui_link_quality(hw, pcurrent_stats);
605}
606
607static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
608 struct sk_buff *skb,
609 struct rtl_stats *pstats,
610 struct rx_desc_92c *pdesc,
611 struct rx_fwinfo_92c *p_drvinfo)
612{
613 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
614 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
615
616 struct ieee80211_hdr *hdr;
617 u8 *tmp_buf;
618 u8 *praddr;
619 u8 *psaddr;
Larry Finger17c9ac62011-02-19 16:29:57 -0600620 __le16 fc;
621 u16 type, c_fc;
Larry Finger7ea47242011-02-19 16:28:57 -0600622 bool packet_matchbssid, packet_toself, packet_beacon;
Larry Finger0c817332010-12-08 11:12:31 -0600623
624 tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
625
626 hdr = (struct ieee80211_hdr *)tmp_buf;
Larry Finger17c9ac62011-02-19 16:29:57 -0600627 fc = hdr->frame_control;
628 c_fc = le16_to_cpu(fc);
Larry Finger0c817332010-12-08 11:12:31 -0600629 type = WLAN_FC_GET_TYPE(fc);
630 praddr = hdr->addr1;
631 psaddr = hdr->addr2;
632
Larry Finger7ea47242011-02-19 16:28:57 -0600633 packet_matchbssid =
Larry Finger0c817332010-12-08 11:12:31 -0600634 ((IEEE80211_FTYPE_CTL != type) &&
635 (!compare_ether_addr(mac->bssid,
Larry Finger17c9ac62011-02-19 16:29:57 -0600636 (c_fc & IEEE80211_FCTL_TODS) ?
637 hdr->addr1 : (c_fc & IEEE80211_FCTL_FROMDS) ?
Larry Finger0c817332010-12-08 11:12:31 -0600638 hdr->addr2 : hdr->addr3)) &&
Larry Finger7ea47242011-02-19 16:28:57 -0600639 (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
Larry Finger0c817332010-12-08 11:12:31 -0600640
Larry Finger7ea47242011-02-19 16:28:57 -0600641 packet_toself = packet_matchbssid &&
Larry Finger0c817332010-12-08 11:12:31 -0600642 (!compare_ether_addr(praddr, rtlefuse->dev_addr));
643
644 if (ieee80211_is_beacon(fc))
Larry Finger7ea47242011-02-19 16:28:57 -0600645 packet_beacon = true;
Larry Finger0c817332010-12-08 11:12:31 -0600646
647 _rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
Larry Finger7ea47242011-02-19 16:28:57 -0600648 packet_matchbssid, packet_toself,
649 packet_beacon);
Larry Finger0c817332010-12-08 11:12:31 -0600650
651 _rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
652}
653
654bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
655 struct rtl_stats *stats,
656 struct ieee80211_rx_status *rx_status,
657 u8 *p_desc, struct sk_buff *skb)
658{
659 struct rx_fwinfo_92c *p_drvinfo;
660 struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
661
662 u32 phystatus = GET_RX_DESC_PHYST(pdesc);
663 stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
664 stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
665 RX_DRV_INFO_SIZE_UNIT;
666 stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
Larry Finger7ea47242011-02-19 16:28:57 -0600667 stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
668 stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
669 stats->hwerror = (stats->crc | stats->icv);
Larry Finger0c817332010-12-08 11:12:31 -0600670 stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
671 stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
Larry Finger7ea47242011-02-19 16:28:57 -0600672 stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
673 stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
674 stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
Larry Finger0c817332010-12-08 11:12:31 -0600675 && (GET_RX_DESC_FAGGR(pdesc) == 1));
676 stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
677 stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
678
679 rx_status->freq = hw->conf.channel->center_freq;
680 rx_status->band = hw->conf.channel->band;
681
682 if (GET_RX_DESC_CRC32(pdesc))
683 rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
684
685 if (!GET_RX_DESC_SWDEC(pdesc))
686 rx_status->flag |= RX_FLAG_DECRYPTED;
687
688 if (GET_RX_DESC_BW(pdesc))
689 rx_status->flag |= RX_FLAG_40MHZ;
690
691 if (GET_RX_DESC_RXHT(pdesc))
692 rx_status->flag |= RX_FLAG_HT;
693
Johannes Berg6ebacbb2011-02-23 15:06:08 +0100694 rx_status->flag |= RX_FLAG_MACTIME_MPDU;
Larry Finger0c817332010-12-08 11:12:31 -0600695
696 if (stats->decrypted)
697 rx_status->flag |= RX_FLAG_DECRYPTED;
698
699 rx_status->rate_idx = _rtl92ce_rate_mapping((bool)
700 GET_RX_DESC_RXHT(pdesc),
701 (u8)
702 GET_RX_DESC_RXMCS(pdesc),
703 (bool)
704 GET_RX_DESC_PAGGR(pdesc));
705
706 rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
707 if (phystatus == true) {
708 p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
709 stats->rx_bufshift);
710
711 _rtl92ce_translate_rx_signal_stuff(hw,
712 skb, stats, pdesc,
713 p_drvinfo);
714 }
715
716 /*rx_status->qual = stats->signal; */
717 rx_status->signal = stats->rssi + 10;
718 /*rx_status->noise = -stats->noise; */
719
720 return true;
721}
722
723void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
724 struct ieee80211_hdr *hdr, u8 *pdesc_tx,
725 struct ieee80211_tx_info *info, struct sk_buff *skb,
726 unsigned int queue_index)
727{
728 struct rtl_priv *rtlpriv = rtl_priv(hw);
729 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
730 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
731 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
Larry Finger7ea47242011-02-19 16:28:57 -0600732 bool defaultadapter = true;
Alessio Igor Bogani701c2be2011-02-28 18:46:44 +0100733 struct ieee80211_sta *sta;
Larry Finger0c817332010-12-08 11:12:31 -0600734 u8 *pdesc = (u8 *) pdesc_tx;
735 struct rtl_tcb_desc tcb_desc;
736 u8 *qc = ieee80211_get_qos_ctl(hdr);
737 u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
738 u16 seq_number;
Larry Finger17c9ac62011-02-19 16:29:57 -0600739 __le16 fc = hdr->frame_control;
Larry Finger0c817332010-12-08 11:12:31 -0600740 u8 rate_flag = info->control.rates[0].flags;
741
742 enum rtl_desc_qsel fw_qsel =
Larry Finger17c9ac62011-02-19 16:29:57 -0600743 _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index);
Larry Finger0c817332010-12-08 11:12:31 -0600744
Larry Finger7ea47242011-02-19 16:28:57 -0600745 bool firstseg = ((hdr->seq_ctrl &
746 cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
Larry Finger0c817332010-12-08 11:12:31 -0600747
Larry Finger7ea47242011-02-19 16:28:57 -0600748 bool lastseg = ((hdr->frame_control &
749 cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
Larry Finger0c817332010-12-08 11:12:31 -0600750
751 dma_addr_t mapping = pci_map_single(rtlpci->pdev,
752 skb->data, skb->len,
753 PCI_DMA_TODEVICE);
754
755 seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
756
757 rtl_get_tcb_desc(hw, info, skb, &tcb_desc);
758
759 CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c));
760
Larry Finger7ea47242011-02-19 16:28:57 -0600761 if (firstseg) {
Larry Finger0c817332010-12-08 11:12:31 -0600762 SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
763
764 SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate);
765
766 if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble)
767 SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
768
769 if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
770 info->flags & IEEE80211_TX_CTL_AMPDU) {
771 SET_TX_DESC_AGG_BREAK(pdesc, 1);
772 SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
773 }
774 SET_TX_DESC_SEQ(pdesc, seq_number);
775
Larry Finger7ea47242011-02-19 16:28:57 -0600776 SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable &&
Larry Finger0c817332010-12-08 11:12:31 -0600777 !tcb_desc.
Larry Finger7ea47242011-02-19 16:28:57 -0600778 cts_enable) ? 1 : 0));
Larry Finger0c817332010-12-08 11:12:31 -0600779 SET_TX_DESC_HW_RTS_ENABLE(pdesc,
Larry Finger7ea47242011-02-19 16:28:57 -0600780 ((tcb_desc.rts_enable
781 || tcb_desc.cts_enable) ? 1 : 0));
782 SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0));
783 SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
Larry Finger0c817332010-12-08 11:12:31 -0600784
785 SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate);
786 SET_TX_DESC_RTS_BW(pdesc, 0);
787 SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc);
788 SET_TX_DESC_RTS_SHORT(pdesc,
789 ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
Larry Finger7ea47242011-02-19 16:28:57 -0600790 (tcb_desc.rts_use_shortpreamble ? 1 : 0)
791 : (tcb_desc.rts_use_shortgi ? 1 : 0)));
Larry Finger0c817332010-12-08 11:12:31 -0600792
793 if (mac->bw_40) {
Larry Finger7ea47242011-02-19 16:28:57 -0600794 if (tcb_desc.packet_bw) {
Larry Finger0c817332010-12-08 11:12:31 -0600795 SET_TX_DESC_DATA_BW(pdesc, 1);
796 SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
797 } else {
798 SET_TX_DESC_DATA_BW(pdesc, 0);
799
800 if (rate_flag & IEEE80211_TX_RC_DUP_DATA) {
801 SET_TX_DESC_TX_SUB_CARRIER(pdesc,
802 mac->cur_40_prime_sc);
803 }
804 }
805 } else {
806 SET_TX_DESC_DATA_BW(pdesc, 0);
807 SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
808 }
809
810 SET_TX_DESC_LINIP(pdesc, 0);
811 SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
812
Alessio Igor Bogani701c2be2011-02-28 18:46:44 +0100813 rcu_read_lock();
814 sta = ieee80211_find_sta(mac->vif, mac->bssid);
Larry Finger0c817332010-12-08 11:12:31 -0600815 if (sta) {
816 u8 ampdu_density = sta->ht_cap.ampdu_density;
817 SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
818 }
Alessio Igor Bogani701c2be2011-02-28 18:46:44 +0100819 rcu_read_unlock();
Larry Finger0c817332010-12-08 11:12:31 -0600820
821 if (info->control.hw_key) {
822 struct ieee80211_key_conf *keyconf =
823 info->control.hw_key;
824
825 switch (keyconf->cipher) {
826 case WLAN_CIPHER_SUITE_WEP40:
827 case WLAN_CIPHER_SUITE_WEP104:
828 case WLAN_CIPHER_SUITE_TKIP:
829 SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
830 break;
831 case WLAN_CIPHER_SUITE_CCMP:
832 SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
833 break;
834 default:
835 SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
836 break;
837
838 }
839 }
840
841 SET_TX_DESC_PKT_ID(pdesc, 0);
842 SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
843
844 SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
845 SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
846 SET_TX_DESC_DISABLE_FB(pdesc, 0);
847 SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0);
848
849 if (ieee80211_is_data_qos(fc)) {
850 if (mac->rdg_en) {
851 RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
852 ("Enable RDG function.\n"));
853 SET_TX_DESC_RDG_ENABLE(pdesc, 1);
854 SET_TX_DESC_HTC(pdesc, 1);
855 }
856 }
857 }
858
Larry Finger7ea47242011-02-19 16:28:57 -0600859 SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
860 SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
Larry Finger0c817332010-12-08 11:12:31 -0600861
862 SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
863
864 SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
865
Larry Finger7ea47242011-02-19 16:28:57 -0600866 if (rtlpriv->dm.useramask) {
Larry Finger0c817332010-12-08 11:12:31 -0600867 SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index);
868 SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id);
869 } else {
870 SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index);
871 SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index);
872 }
873
Larry Finger7ea47242011-02-19 16:28:57 -0600874 if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
875 ppsc->fwctrl_lps) {
Larry Finger0c817332010-12-08 11:12:31 -0600876 SET_TX_DESC_HWSEQ_EN(pdesc, 1);
877 SET_TX_DESC_PKT_ID(pdesc, 8);
878
Larry Finger7ea47242011-02-19 16:28:57 -0600879 if (!defaultadapter)
Larry Finger0c817332010-12-08 11:12:31 -0600880 SET_TX_DESC_QOS(pdesc, 1);
881 }
882
Larry Finger7ea47242011-02-19 16:28:57 -0600883 SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
Larry Finger0c817332010-12-08 11:12:31 -0600884
885 if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
886 is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
887 SET_TX_DESC_BMC(pdesc, 1);
888 }
889
890 RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
891}
892
893void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
Larry Finger7ea47242011-02-19 16:28:57 -0600894 u8 *pdesc, bool firstseg,
895 bool lastseg, struct sk_buff *skb)
Larry Finger0c817332010-12-08 11:12:31 -0600896{
897 struct rtl_priv *rtlpriv = rtl_priv(hw);
898 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
899 u8 fw_queue = QSLT_BEACON;
900
901 dma_addr_t mapping = pci_map_single(rtlpci->pdev,
902 skb->data, skb->len,
903 PCI_DMA_TODEVICE);
904
905 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
Larry Finger17c9ac62011-02-19 16:29:57 -0600906 __le16 fc = hdr->frame_control;
Larry Finger0c817332010-12-08 11:12:31 -0600907
908 CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
909
Larry Finger7ea47242011-02-19 16:28:57 -0600910 if (firstseg)
Larry Finger0c817332010-12-08 11:12:31 -0600911 SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
912
913 SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
914
915 SET_TX_DESC_SEQ(pdesc, 0);
916
917 SET_TX_DESC_LINIP(pdesc, 0);
918
919 SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
920
921 SET_TX_DESC_FIRST_SEG(pdesc, 1);
922 SET_TX_DESC_LAST_SEG(pdesc, 1);
923
924 SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
925
926 SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
927
928 SET_TX_DESC_RATE_ID(pdesc, 7);
929 SET_TX_DESC_MACID(pdesc, 0);
930
931 SET_TX_DESC_OWN(pdesc, 1);
932
933 SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
934
935 SET_TX_DESC_FIRST_SEG(pdesc, 1);
936 SET_TX_DESC_LAST_SEG(pdesc, 1);
937
938 SET_TX_DESC_OFFSET(pdesc, 0x20);
939
940 SET_TX_DESC_USE_RATE(pdesc, 1);
941
942 if (!ieee80211_is_data_qos(fc)) {
943 SET_TX_DESC_HWSEQ_EN(pdesc, 1);
944 SET_TX_DESC_PKT_ID(pdesc, 8);
945 }
946
947 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
948 "H2C Tx Cmd Content\n",
949 pdesc, TX_DESC_SIZE);
950}
951
952void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
953{
954 if (istx == true) {
955 switch (desc_name) {
956 case HW_DESC_OWN:
957 SET_TX_DESC_OWN(pdesc, 1);
958 break;
959 case HW_DESC_TX_NEXTDESC_ADDR:
960 SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
961 break;
962 default:
963 RT_ASSERT(false, ("ERR txdesc :%d"
964 " not process\n", desc_name));
965 break;
966 }
967 } else {
968 switch (desc_name) {
969 case HW_DESC_RXOWN:
970 SET_RX_DESC_OWN(pdesc, 1);
971 break;
972 case HW_DESC_RXBUFF_ADDR:
973 SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
974 break;
975 case HW_DESC_RXPKT_LEN:
976 SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
977 break;
978 case HW_DESC_RXERO:
979 SET_RX_DESC_EOR(pdesc, 1);
980 break;
981 default:
982 RT_ASSERT(false, ("ERR rxdesc :%d "
983 "not process\n", desc_name));
984 break;
985 }
986 }
987}
988
989u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
990{
991 u32 ret = 0;
992
993 if (istx == true) {
994 switch (desc_name) {
995 case HW_DESC_OWN:
996 ret = GET_TX_DESC_OWN(p_desc);
997 break;
998 case HW_DESC_TXBUFF_ADDR:
999 ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
1000 break;
1001 default:
1002 RT_ASSERT(false, ("ERR txdesc :%d "
1003 "not process\n", desc_name));
1004 break;
1005 }
1006 } else {
1007 struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
1008 switch (desc_name) {
1009 case HW_DESC_OWN:
1010 ret = GET_RX_DESC_OWN(pdesc);
1011 break;
1012 case HW_DESC_RXPKT_LEN:
1013 ret = GET_RX_DESC_PKT_LEN(pdesc);
1014 break;
1015 default:
1016 RT_ASSERT(false, ("ERR rxdesc :%d "
1017 "not process\n", desc_name));
1018 break;
1019 }
1020 }
1021 return ret;
1022}
1023
1024void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue)
1025{
1026 struct rtl_priv *rtlpriv = rtl_priv(hw);
1027 if (hw_queue == BEACON_QUEUE) {
1028 rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
1029 } else {
1030 rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
1031 BIT(0) << (hw_queue));
1032 }
1033}
Larry Finger25b2bc32011-02-11 14:34:03 -06001034
1035bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
1036 struct sk_buff *skb)
1037{
1038 struct rtl_priv *rtlpriv = rtl_priv(hw);
1039 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1040 struct rtl8192_tx_ring *ring;
1041 struct rtl_tx_desc *pdesc;
1042 u8 own;
1043 unsigned long flags;
1044 struct sk_buff *pskb = NULL;
1045
1046 ring = &rtlpci->tx_ring[BEACON_QUEUE];
1047
1048 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
1049
1050 pskb = __skb_dequeue(&ring->queue);
1051 if (pskb)
1052 kfree_skb(pskb);
1053
1054 pdesc = &ring->desc[0];
1055 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
1056
1057 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
1058
1059 __skb_queue_tail(&ring->queue, skb);
1060
1061 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
1062
1063 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
1064
1065 return true;
1066}