1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. |
5 | * |
6 | ******************************************************************************/ |
7 | #include <drv_types.h> |
8 | #include <rtw_debug.h> |
9 | #include <linux/jiffies.h> |
10 | #include <rtw_recv.h> |
11 | #include <net/cfg80211.h> |
12 | #include <asm/unaligned.h> |
13 | |
14 | static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; |
15 | static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; |
16 | |
17 | static void rtw_signal_stat_timer_hdl(struct timer_list *t); |
18 | |
19 | void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) |
20 | { |
21 | memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv)); |
22 | |
23 | spin_lock_init(&psta_recvpriv->lock); |
24 | |
25 | /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */ |
26 | /* _rtw_init_queue(&psta_recvpriv->blk_strms[i]); */ |
27 | |
28 | INIT_LIST_HEAD(list: &psta_recvpriv->defrag_q.queue); |
29 | spin_lock_init(&psta_recvpriv->defrag_q.lock); |
30 | } |
31 | |
32 | signed int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) |
33 | { |
34 | signed int i; |
35 | union recv_frame *precvframe; |
36 | signed int res = _SUCCESS; |
37 | |
38 | spin_lock_init(&precvpriv->lock); |
39 | |
40 | INIT_LIST_HEAD(list: &precvpriv->free_recv_queue.queue); |
41 | spin_lock_init(&precvpriv->free_recv_queue.lock); |
42 | INIT_LIST_HEAD(list: &precvpriv->recv_pending_queue.queue); |
43 | spin_lock_init(&precvpriv->recv_pending_queue.lock); |
44 | INIT_LIST_HEAD(list: &precvpriv->uc_swdec_pending_queue.queue); |
45 | spin_lock_init(&precvpriv->uc_swdec_pending_queue.lock); |
46 | |
47 | precvpriv->adapter = padapter; |
48 | |
49 | precvpriv->free_recvframe_cnt = NR_RECVFRAME; |
50 | |
51 | precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); |
52 | |
53 | if (!precvpriv->pallocated_frame_buf) { |
54 | res = _FAIL; |
55 | goto exit; |
56 | } |
57 | |
58 | precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); |
59 | /* precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - */ |
60 | /* ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1)); */ |
61 | |
62 | precvframe = (union recv_frame *) precvpriv->precv_frame_buf; |
63 | |
64 | |
65 | for (i = 0; i < NR_RECVFRAME; i++) { |
66 | INIT_LIST_HEAD(list: &(precvframe->u.list)); |
67 | |
68 | list_add_tail(new: &(precvframe->u.list), head: &(precvpriv->free_recv_queue.queue)); |
69 | |
70 | rtw_os_recv_resource_alloc(padapter, precvframe); |
71 | |
72 | precvframe->u.hdr.len = 0; |
73 | |
74 | precvframe->u.hdr.adapter = padapter; |
75 | precvframe++; |
76 | |
77 | } |
78 | |
79 | res = rtw_hal_init_recv_priv(padapter); |
80 | |
81 | timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl, |
82 | 0); |
83 | |
84 | precvpriv->signal_stat_sampling_interval = 2000; /* ms */ |
85 | |
86 | rtw_set_signal_stat_timer(precvpriv); |
87 | |
88 | exit: |
89 | return res; |
90 | } |
91 | |
92 | void _rtw_free_recv_priv(struct recv_priv *precvpriv) |
93 | { |
94 | struct adapter *padapter = precvpriv->adapter; |
95 | |
96 | rtw_free_uc_swdec_pending_queue(adapter: padapter); |
97 | |
98 | rtw_os_recv_resource_free(precvpriv); |
99 | |
100 | vfree(addr: precvpriv->pallocated_frame_buf); |
101 | |
102 | rtw_hal_free_recv_priv(padapter); |
103 | } |
104 | |
105 | union recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) |
106 | { |
107 | |
108 | union recv_frame *precvframe; |
109 | struct list_head *plist, *phead; |
110 | struct adapter *padapter; |
111 | struct recv_priv *precvpriv; |
112 | |
113 | if (list_empty(head: &pfree_recv_queue->queue)) |
114 | precvframe = NULL; |
115 | else { |
116 | phead = get_list_head(queue: pfree_recv_queue); |
117 | |
118 | plist = get_next(list: phead); |
119 | |
120 | precvframe = (union recv_frame *)plist; |
121 | |
122 | list_del_init(entry: &precvframe->u.hdr.list); |
123 | padapter = precvframe->u.hdr.adapter; |
124 | if (padapter) { |
125 | precvpriv = &padapter->recvpriv; |
126 | if (pfree_recv_queue == &precvpriv->free_recv_queue) |
127 | precvpriv->free_recvframe_cnt--; |
128 | } |
129 | } |
130 | return precvframe; |
131 | } |
132 | |
133 | union recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue) |
134 | { |
135 | union recv_frame *precvframe; |
136 | |
137 | spin_lock_bh(lock: &pfree_recv_queue->lock); |
138 | |
139 | precvframe = _rtw_alloc_recvframe(pfree_recv_queue); |
140 | |
141 | spin_unlock_bh(lock: &pfree_recv_queue->lock); |
142 | |
143 | return precvframe; |
144 | } |
145 | |
146 | int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue) |
147 | { |
148 | struct adapter *padapter = precvframe->u.hdr.adapter; |
149 | struct recv_priv *precvpriv = &padapter->recvpriv; |
150 | |
151 | rtw_os_free_recvframe(precvframe); |
152 | |
153 | |
154 | spin_lock_bh(lock: &pfree_recv_queue->lock); |
155 | |
156 | list_del_init(entry: &(precvframe->u.hdr.list)); |
157 | |
158 | precvframe->u.hdr.len = 0; |
159 | |
160 | list_add_tail(new: &(precvframe->u.hdr.list), head: get_list_head(queue: pfree_recv_queue)); |
161 | |
162 | if (padapter) { |
163 | if (pfree_recv_queue == &precvpriv->free_recv_queue) |
164 | precvpriv->free_recvframe_cnt++; |
165 | } |
166 | spin_unlock_bh(lock: &pfree_recv_queue->lock); |
167 | return _SUCCESS; |
168 | } |
169 | |
170 | |
171 | |
172 | |
173 | signed int _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue) |
174 | { |
175 | |
176 | struct adapter *padapter = precvframe->u.hdr.adapter; |
177 | struct recv_priv *precvpriv = &padapter->recvpriv; |
178 | |
179 | /* INIT_LIST_HEAD(&(precvframe->u.hdr.list)); */ |
180 | list_del_init(entry: &(precvframe->u.hdr.list)); |
181 | |
182 | |
183 | list_add_tail(new: &(precvframe->u.hdr.list), head: get_list_head(queue)); |
184 | |
185 | if (padapter) |
186 | if (queue == &precvpriv->free_recv_queue) |
187 | precvpriv->free_recvframe_cnt++; |
188 | |
189 | return _SUCCESS; |
190 | } |
191 | |
192 | signed int rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue) |
193 | { |
194 | signed int ret; |
195 | |
196 | /* _spinlock(&pfree_recv_queue->lock); */ |
197 | spin_lock_bh(lock: &queue->lock); |
198 | ret = _rtw_enqueue_recvframe(precvframe, queue); |
199 | /* spin_unlock(&pfree_recv_queue->lock); */ |
200 | spin_unlock_bh(lock: &queue->lock); |
201 | |
202 | return ret; |
203 | } |
204 | |
205 | /* |
206 | * caller : defrag ; recvframe_chk_defrag in recv_thread (passive) |
207 | * pframequeue: defrag_queue : will be accessed in recv_thread (passive) |
208 | * |
209 | * using spinlock to protect |
210 | * |
211 | */ |
212 | |
213 | void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue) |
214 | { |
215 | union recv_frame *precvframe; |
216 | struct list_head *plist, *phead; |
217 | |
218 | spin_lock(lock: &pframequeue->lock); |
219 | |
220 | phead = get_list_head(queue: pframequeue); |
221 | plist = get_next(list: phead); |
222 | |
223 | while (phead != plist) { |
224 | precvframe = (union recv_frame *)plist; |
225 | |
226 | plist = get_next(list: plist); |
227 | |
228 | rtw_free_recvframe(precvframe, pfree_recv_queue); |
229 | } |
230 | |
231 | spin_unlock(lock: &pframequeue->lock); |
232 | } |
233 | |
234 | u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter) |
235 | { |
236 | u32 cnt = 0; |
237 | union recv_frame *pending_frame; |
238 | |
239 | while ((pending_frame = rtw_alloc_recvframe(pfree_recv_queue: &adapter->recvpriv.uc_swdec_pending_queue))) { |
240 | rtw_free_recvframe(precvframe: pending_frame, pfree_recv_queue: &adapter->recvpriv.free_recv_queue); |
241 | cnt++; |
242 | } |
243 | |
244 | return cnt; |
245 | } |
246 | |
247 | |
248 | signed int rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, struct __queue *queue) |
249 | { |
250 | spin_lock_bh(lock: &queue->lock); |
251 | |
252 | list_del_init(entry: &precvbuf->list); |
253 | list_add(new: &precvbuf->list, head: get_list_head(queue)); |
254 | |
255 | spin_unlock_bh(lock: &queue->lock); |
256 | |
257 | return _SUCCESS; |
258 | } |
259 | |
260 | signed int rtw_enqueue_recvbuf(struct recv_buf *precvbuf, struct __queue *queue) |
261 | { |
262 | spin_lock_bh(lock: &queue->lock); |
263 | |
264 | list_del_init(entry: &precvbuf->list); |
265 | |
266 | list_add_tail(new: &precvbuf->list, head: get_list_head(queue)); |
267 | spin_unlock_bh(lock: &queue->lock); |
268 | return _SUCCESS; |
269 | |
270 | } |
271 | |
272 | struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue) |
273 | { |
274 | struct recv_buf *precvbuf; |
275 | struct list_head *plist, *phead; |
276 | |
277 | spin_lock_bh(lock: &queue->lock); |
278 | |
279 | if (list_empty(head: &queue->queue)) |
280 | precvbuf = NULL; |
281 | else { |
282 | phead = get_list_head(queue); |
283 | |
284 | plist = get_next(list: phead); |
285 | |
286 | precvbuf = container_of(plist, struct recv_buf, list); |
287 | |
288 | list_del_init(entry: &precvbuf->list); |
289 | |
290 | } |
291 | |
292 | spin_unlock_bh(lock: &queue->lock); |
293 | |
294 | return precvbuf; |
295 | |
296 | } |
297 | |
298 | static signed int recvframe_chkmic(struct adapter *adapter, union recv_frame *precvframe) |
299 | { |
300 | |
301 | signed int i, res = _SUCCESS; |
302 | u32 datalen; |
303 | u8 miccode[8]; |
304 | u8 bmic_err = false, brpt_micerror = true; |
305 | u8 *pframe, *payload, *pframemic; |
306 | u8 *mickey; |
307 | /* u8 *iv, rxdata_key_idx = 0; */ |
308 | struct sta_info *stainfo; |
309 | struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib; |
310 | struct security_priv *psecuritypriv = &adapter->securitypriv; |
311 | |
312 | struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; |
313 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
314 | |
315 | stainfo = rtw_get_stainfo(pstapriv: &adapter->stapriv, hwaddr: &prxattrib->ta[0]); |
316 | |
317 | if (prxattrib->encrypt == _TKIP_) { |
318 | /* calculate mic code */ |
319 | if (stainfo) { |
320 | if (is_multicast_ether_addr(addr: prxattrib->ra)) { |
321 | /* mickey =&psecuritypriv->dot118021XGrprxmickey.skey[0]; */ |
322 | /* iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; */ |
323 | /* rxdata_key_idx =(((iv[3])>>6)&0x3) ; */ |
324 | mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; |
325 | |
326 | /* psecuritypriv->dot118021XGrpKeyid, pmlmeinfo->key_index, rxdata_key_idx); */ |
327 | |
328 | if (psecuritypriv->binstallGrpkey == false) { |
329 | res = _FAIL; |
330 | goto exit; |
331 | } |
332 | } else { |
333 | mickey = &stainfo->dot11tkiprxmickey.skey[0]; |
334 | } |
335 | |
336 | datalen = precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;/* icv_len included the mic code */ |
337 | pframe = precvframe->u.hdr.rx_data; |
338 | payload = pframe+prxattrib->hdrlen+prxattrib->iv_len; |
339 | |
340 | rtw_seccalctkipmic(key: mickey, header: pframe, data: payload, data_len: datalen, Miccode: &miccode[0], priority: (unsigned char)prxattrib->priority); /* care the length of the data */ |
341 | |
342 | pframemic = payload+datalen; |
343 | |
344 | bmic_err = false; |
345 | |
346 | for (i = 0; i < 8; i++) { |
347 | if (miccode[i] != *(pframemic + i)) |
348 | bmic_err = true; |
349 | } |
350 | |
351 | |
352 | if (bmic_err == true) { |
353 | /* double check key_index for some timing issue , */ |
354 | /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */ |
355 | if ((is_multicast_ether_addr(addr: prxattrib->ra) == true) && (prxattrib->key_index != pmlmeinfo->key_index)) |
356 | brpt_micerror = false; |
357 | |
358 | if (prxattrib->bdecrypted && brpt_micerror) |
359 | rtw_handle_tkip_mic_err(padapter: adapter, bgroup: (u8)is_multicast_ether_addr(addr: prxattrib->ra)); |
360 | |
361 | res = _FAIL; |
362 | |
363 | } else { |
364 | /* mic checked ok */ |
365 | if (!psecuritypriv->bcheck_grpkey && |
366 | is_multicast_ether_addr(addr: prxattrib->ra)) |
367 | psecuritypriv->bcheck_grpkey = true; |
368 | } |
369 | } |
370 | |
371 | recvframe_pull_tail(precvframe, sz: 8); |
372 | |
373 | } |
374 | |
375 | exit: |
376 | return res; |
377 | |
378 | } |
379 | |
380 | /* decrypt and set the ivlen, icvlen of the recv_frame */ |
381 | static union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame) |
382 | { |
383 | |
384 | struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib; |
385 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
386 | union recv_frame *return_packet = precv_frame; |
387 | u32 res = _SUCCESS; |
388 | |
389 | if (prxattrib->encrypt > 0) { |
390 | u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen; |
391 | |
392 | prxattrib->key_index = (((iv[3])>>6)&0x3); |
393 | |
394 | if (prxattrib->key_index > WEP_KEYS) { |
395 | switch (prxattrib->encrypt) { |
396 | case _WEP40_: |
397 | case _WEP104_: |
398 | prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex; |
399 | break; |
400 | case _TKIP_: |
401 | case _AES_: |
402 | default: |
403 | prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid; |
404 | break; |
405 | } |
406 | } |
407 | } |
408 | |
409 | if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || (psecuritypriv->sw_decrypt == true))) { |
410 | psecuritypriv->hw_decrypted = false; |
411 | |
412 | switch (prxattrib->encrypt) { |
413 | case _WEP40_: |
414 | case _WEP104_: |
415 | rtw_wep_decrypt(padapter, precvframe: (u8 *)precv_frame); |
416 | break; |
417 | case _TKIP_: |
418 | res = rtw_tkip_decrypt(padapter, precvframe: (u8 *)precv_frame); |
419 | break; |
420 | case _AES_: |
421 | res = rtw_aes_decrypt(padapter, precvframe: (u8 *)precv_frame); |
422 | break; |
423 | default: |
424 | break; |
425 | } |
426 | } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 && |
427 | (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_) |
428 | ) { |
429 | psecuritypriv->hw_decrypted = true; |
430 | } else { |
431 | } |
432 | |
433 | if (res == _FAIL) { |
434 | rtw_free_recvframe(precvframe: return_packet, pfree_recv_queue: &padapter->recvpriv.free_recv_queue); |
435 | return_packet = NULL; |
436 | } else |
437 | prxattrib->bdecrypted = true; |
438 | |
439 | return return_packet; |
440 | } |
441 | |
442 | /* set the security information in the recv_frame */ |
443 | static union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame) |
444 | { |
445 | u8 *psta_addr = NULL; |
446 | u8 *ptr; |
447 | uint auth_alg; |
448 | struct recv_frame_hdr *pfhdr; |
449 | struct sta_info *psta; |
450 | struct sta_priv *pstapriv; |
451 | union recv_frame *prtnframe; |
452 | u16 ether_type = 0; |
453 | u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */ |
454 | struct rx_pkt_attrib *pattrib; |
455 | |
456 | pstapriv = &adapter->stapriv; |
457 | |
458 | auth_alg = adapter->securitypriv.dot11AuthAlgrthm; |
459 | |
460 | ptr = precv_frame->u.hdr.rx_data; |
461 | pfhdr = &precv_frame->u.hdr; |
462 | pattrib = &pfhdr->attrib; |
463 | psta_addr = pattrib->ta; |
464 | |
465 | prtnframe = NULL; |
466 | |
467 | psta = rtw_get_stainfo(pstapriv, hwaddr: psta_addr); |
468 | |
469 | if (auth_alg == 2) { |
470 | if ((psta) && (psta->ieee8021x_blocked)) { |
471 | __be16 be_tmp; |
472 | |
473 | /* blocked */ |
474 | /* only accept EAPOL frame */ |
475 | |
476 | prtnframe = precv_frame; |
477 | |
478 | /* get ether_type */ |
479 | ptr = ptr + pfhdr->attrib.hdrlen + pfhdr->attrib.iv_len + LLC_HEADER_LENGTH; |
480 | memcpy(&be_tmp, ptr, 2); |
481 | ether_type = ntohs(be_tmp); |
482 | |
483 | if (ether_type == eapol_type) |
484 | prtnframe = precv_frame; |
485 | else { |
486 | /* free this frame */ |
487 | rtw_free_recvframe(precvframe: precv_frame, pfree_recv_queue: &adapter->recvpriv.free_recv_queue); |
488 | prtnframe = NULL; |
489 | } |
490 | } else { |
491 | /* allowed */ |
492 | /* check decryption status, and decrypt the frame if needed */ |
493 | |
494 | prtnframe = precv_frame; |
495 | /* check is the EAPOL frame or not (Rekey) */ |
496 | /* if (ether_type == eapol_type) { */ |
497 | /* check Rekey */ |
498 | |
499 | /* prtnframe =precv_frame; */ |
500 | /* */ |
501 | /* else { */ |
502 | /* */ |
503 | } |
504 | } else |
505 | prtnframe = precv_frame; |
506 | |
507 | return prtnframe; |
508 | } |
509 | |
510 | static signed int recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache) |
511 | { |
512 | signed int tid = precv_frame->u.hdr.attrib.priority; |
513 | |
514 | u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | |
515 | (precv_frame->u.hdr.attrib.frag_num & 0xf); |
516 | |
517 | if (tid > 15) |
518 | return _FAIL; |
519 | |
520 | if (1) { /* if (bretry) */ |
521 | if (seq_ctrl == prxcache->tid_rxseq[tid]) |
522 | return _FAIL; |
523 | } |
524 | |
525 | prxcache->tid_rxseq[tid] = seq_ctrl; |
526 | |
527 | return _SUCCESS; |
528 | |
529 | } |
530 | |
531 | static void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame) |
532 | { |
533 | unsigned char pwrbit; |
534 | u8 *ptr = precv_frame->u.hdr.rx_data; |
535 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
536 | struct sta_priv *pstapriv = &padapter->stapriv; |
537 | struct sta_info *psta = NULL; |
538 | |
539 | psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->src); |
540 | |
541 | pwrbit = GetPwrMgt(ptr); |
542 | |
543 | if (psta) { |
544 | if (pwrbit) { |
545 | if (!(psta->state & WIFI_SLEEP_STATE)) { |
546 | /* psta->state |= WIFI_SLEEP_STATE; */ |
547 | /* pstapriv->sta_dz_bitmap |= BIT(psta->aid); */ |
548 | |
549 | stop_sta_xmit(padapter, psta); |
550 | |
551 | } |
552 | } else { |
553 | if (psta->state & WIFI_SLEEP_STATE) { |
554 | /* psta->state ^= WIFI_SLEEP_STATE; */ |
555 | /* pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); */ |
556 | |
557 | wakeup_sta_to_xmit(padapter, psta); |
558 | } |
559 | } |
560 | |
561 | } |
562 | } |
563 | |
564 | static void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame) |
565 | { |
566 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
567 | struct sta_priv *pstapriv = &padapter->stapriv; |
568 | struct sta_info *psta = NULL; |
569 | |
570 | psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->src); |
571 | |
572 | if (!psta) |
573 | return; |
574 | |
575 | if (!psta->qos_option) |
576 | return; |
577 | |
578 | if (!(psta->qos_info&0xf)) |
579 | return; |
580 | |
581 | if (psta->state&WIFI_SLEEP_STATE) { |
582 | u8 wmmps_ac = 0; |
583 | |
584 | switch (pattrib->priority) { |
585 | case 1: |
586 | case 2: |
587 | wmmps_ac = psta->uapsd_bk&BIT(1); |
588 | break; |
589 | case 4: |
590 | case 5: |
591 | wmmps_ac = psta->uapsd_vi&BIT(1); |
592 | break; |
593 | case 6: |
594 | case 7: |
595 | wmmps_ac = psta->uapsd_vo&BIT(1); |
596 | break; |
597 | case 0: |
598 | case 3: |
599 | default: |
600 | wmmps_ac = psta->uapsd_be&BIT(1); |
601 | break; |
602 | } |
603 | |
604 | if (wmmps_ac) { |
605 | if (psta->sleepq_ac_len > 0) |
606 | /* process received triggered frame */ |
607 | xmit_delivery_enabled_frames(padapter, psta); |
608 | else |
609 | /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */ |
610 | issue_qos_nulldata(padapter, da: psta->hwaddr, tid: (u16)pattrib->priority, try_cnt: 0, wait_ms: 0); |
611 | } |
612 | } |
613 | } |
614 | |
615 | static void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta) |
616 | { |
617 | int sz; |
618 | struct sta_info *psta = NULL; |
619 | struct stainfo_stats *pstats = NULL; |
620 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; |
621 | struct recv_priv *precvpriv = &padapter->recvpriv; |
622 | |
623 | sz = get_recvframe_len(precvframe: prframe); |
624 | precvpriv->rx_bytes += sz; |
625 | |
626 | padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; |
627 | |
628 | if ((!is_broadcast_ether_addr(addr: pattrib->dst)) && (!is_multicast_ether_addr(addr: pattrib->dst))) |
629 | padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; |
630 | |
631 | if (sta) |
632 | psta = sta; |
633 | else |
634 | psta = prframe->u.hdr.psta; |
635 | |
636 | if (psta) { |
637 | pstats = &psta->sta_stats; |
638 | |
639 | pstats->rx_data_pkts++; |
640 | pstats->rx_bytes += sz; |
641 | } |
642 | |
643 | traffic_check_for_leave_lps(padapter, tx: false, tx_packets: 0); |
644 | } |
645 | |
646 | static signed int sta2sta_data_frame(struct adapter *adapter, union recv_frame *precv_frame, |
647 | struct sta_info **psta) |
648 | { |
649 | u8 *ptr = precv_frame->u.hdr.rx_data; |
650 | signed int ret = _SUCCESS; |
651 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
652 | struct sta_priv *pstapriv = &adapter->stapriv; |
653 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
654 | u8 *mybssid = get_bssid(pmlmepriv); |
655 | u8 *myhwaddr = myid(peepriv: &adapter->eeprompriv); |
656 | u8 *sta_addr = NULL; |
657 | signed int bmcast = is_multicast_ether_addr(addr: pattrib->dst); |
658 | |
659 | if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) || |
660 | (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) { |
661 | |
662 | /* filter packets that SA is myself or multicast or broadcast */ |
663 | if (!memcmp(p: myhwaddr, q: pattrib->src, ETH_ALEN)) { |
664 | ret = _FAIL; |
665 | goto exit; |
666 | } |
667 | |
668 | if ((memcmp(p: myhwaddr, q: pattrib->dst, ETH_ALEN)) && (!bmcast)) { |
669 | ret = _FAIL; |
670 | goto exit; |
671 | } |
672 | |
673 | if (is_zero_ether_addr(addr: pattrib->bssid) || |
674 | is_zero_ether_addr(addr: mybssid) || |
675 | (memcmp(p: pattrib->bssid, q: mybssid, ETH_ALEN))) { |
676 | ret = _FAIL; |
677 | goto exit; |
678 | } |
679 | |
680 | sta_addr = pattrib->src; |
681 | |
682 | } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { |
683 | /* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */ |
684 | if (memcmp(p: pattrib->bssid, q: pattrib->src, ETH_ALEN)) { |
685 | ret = _FAIL; |
686 | goto exit; |
687 | } |
688 | |
689 | sta_addr = pattrib->bssid; |
690 | } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { |
691 | if (bmcast) { |
692 | /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ |
693 | if (!is_multicast_ether_addr(addr: pattrib->bssid)) { |
694 | ret = _FAIL; |
695 | goto exit; |
696 | } |
697 | } else { /* not mc-frame */ |
698 | /* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */ |
699 | if (memcmp(p: pattrib->bssid, q: pattrib->dst, ETH_ALEN)) { |
700 | ret = _FAIL; |
701 | goto exit; |
702 | } |
703 | |
704 | sta_addr = pattrib->src; |
705 | } |
706 | |
707 | } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) { |
708 | memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); |
709 | memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); |
710 | memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); |
711 | memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); |
712 | memcpy(pattrib->ta, pattrib->src, ETH_ALEN); |
713 | |
714 | sta_addr = mybssid; |
715 | } else |
716 | ret = _FAIL; |
717 | |
718 | |
719 | |
720 | if (bmcast) |
721 | *psta = rtw_get_bcmc_stainfo(padapter: adapter); |
722 | else |
723 | *psta = rtw_get_stainfo(pstapriv, hwaddr: sta_addr); /* get ap_info */ |
724 | |
725 | if (!*psta) { |
726 | ret = _FAIL; |
727 | goto exit; |
728 | } |
729 | |
730 | exit: |
731 | return ret; |
732 | } |
733 | |
734 | static signed int ap2sta_data_frame(struct adapter *adapter, union recv_frame *precv_frame, |
735 | struct sta_info **psta) |
736 | { |
737 | u8 *ptr = precv_frame->u.hdr.rx_data; |
738 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
739 | signed int ret = _SUCCESS; |
740 | struct sta_priv *pstapriv = &adapter->stapriv; |
741 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
742 | u8 *mybssid = get_bssid(pmlmepriv); |
743 | u8 *myhwaddr = myid(peepriv: &adapter->eeprompriv); |
744 | signed int bmcast = is_multicast_ether_addr(addr: pattrib->dst); |
745 | |
746 | if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) && |
747 | (check_fwstate(pmlmepriv, _FW_LINKED) == true || |
748 | check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) |
749 | ) { |
750 | |
751 | /* filter packets that SA is myself or multicast or broadcast */ |
752 | if (!memcmp(p: myhwaddr, q: pattrib->src, ETH_ALEN)) { |
753 | ret = _FAIL; |
754 | goto exit; |
755 | } |
756 | |
757 | /* da should be for me */ |
758 | if ((memcmp(p: myhwaddr, q: pattrib->dst, ETH_ALEN)) && (!bmcast)) { |
759 | ret = _FAIL; |
760 | goto exit; |
761 | } |
762 | |
763 | |
764 | /* check BSSID */ |
765 | if (is_zero_ether_addr(addr: pattrib->bssid) || |
766 | is_zero_ether_addr(addr: mybssid) || |
767 | (memcmp(p: pattrib->bssid, q: mybssid, ETH_ALEN))) { |
768 | |
769 | if (!bmcast) |
770 | issue_deauth(padapter: adapter, da: pattrib->bssid, reason: WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); |
771 | |
772 | ret = _FAIL; |
773 | goto exit; |
774 | } |
775 | |
776 | if (bmcast) |
777 | *psta = rtw_get_bcmc_stainfo(padapter: adapter); |
778 | else |
779 | *psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->bssid); /* get ap_info */ |
780 | |
781 | if (!*psta) { |
782 | ret = _FAIL; |
783 | goto exit; |
784 | } |
785 | |
786 | if (GetFrameSubType(ptr) & BIT(6)) { |
787 | /* No data, will not indicate to upper layer, temporily count it here */ |
788 | count_rx_stats(padapter: adapter, prframe: precv_frame, sta: *psta); |
789 | ret = RTW_RX_HANDLED; |
790 | goto exit; |
791 | } |
792 | |
793 | } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && |
794 | (check_fwstate(pmlmepriv, _FW_LINKED) == true)) { |
795 | memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); |
796 | memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); |
797 | memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); |
798 | memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); |
799 | memcpy(pattrib->ta, pattrib->src, ETH_ALEN); |
800 | |
801 | /* */ |
802 | memcpy(pattrib->bssid, mybssid, ETH_ALEN); |
803 | |
804 | |
805 | *psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->bssid); /* get sta_info */ |
806 | if (!*psta) { |
807 | ret = _FAIL; |
808 | goto exit; |
809 | } |
810 | |
811 | |
812 | } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { |
813 | /* Special case */ |
814 | ret = RTW_RX_HANDLED; |
815 | goto exit; |
816 | } else { |
817 | if (!memcmp(p: myhwaddr, q: pattrib->dst, ETH_ALEN) && (!bmcast)) { |
818 | *psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->bssid); /* get sta_info */ |
819 | if (!*psta) { |
820 | |
821 | /* for AP multicast issue , modify by yiwei */ |
822 | static unsigned long send_issue_deauth_time; |
823 | |
824 | if (jiffies_to_msecs(j: jiffies - send_issue_deauth_time) > 10000 || send_issue_deauth_time == 0) { |
825 | send_issue_deauth_time = jiffies; |
826 | |
827 | issue_deauth(padapter: adapter, da: pattrib->bssid, reason: WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); |
828 | } |
829 | } |
830 | } |
831 | |
832 | ret = _FAIL; |
833 | } |
834 | |
835 | exit: |
836 | return ret; |
837 | } |
838 | |
839 | static signed int sta2ap_data_frame(struct adapter *adapter, union recv_frame *precv_frame, |
840 | struct sta_info **psta) |
841 | { |
842 | u8 *ptr = precv_frame->u.hdr.rx_data; |
843 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
844 | struct sta_priv *pstapriv = &adapter->stapriv; |
845 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
846 | unsigned char *mybssid = get_bssid(pmlmepriv); |
847 | signed int ret = _SUCCESS; |
848 | |
849 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { |
850 | /* For AP mode, RA =BSSID, TX =STA(SRC_ADDR), A3 =DST_ADDR */ |
851 | if (memcmp(p: pattrib->bssid, q: mybssid, ETH_ALEN)) { |
852 | ret = _FAIL; |
853 | goto exit; |
854 | } |
855 | |
856 | *psta = rtw_get_stainfo(pstapriv, hwaddr: pattrib->src); |
857 | if (!*psta) { |
858 | issue_deauth(padapter: adapter, da: pattrib->src, reason: WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); |
859 | |
860 | ret = RTW_RX_HANDLED; |
861 | goto exit; |
862 | } |
863 | |
864 | process_pwrbit_data(padapter: adapter, precv_frame); |
865 | |
866 | if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) |
867 | process_wmmps_data(padapter: adapter, precv_frame); |
868 | |
869 | if (GetFrameSubType(ptr) & BIT(6)) { |
870 | /* No data, will not indicate to upper layer, temporily count it here */ |
871 | count_rx_stats(padapter: adapter, prframe: precv_frame, sta: *psta); |
872 | ret = RTW_RX_HANDLED; |
873 | goto exit; |
874 | } |
875 | } else { |
876 | u8 *myhwaddr = myid(peepriv: &adapter->eeprompriv); |
877 | |
878 | if (memcmp(p: pattrib->ra, q: myhwaddr, ETH_ALEN)) { |
879 | ret = RTW_RX_HANDLED; |
880 | goto exit; |
881 | } |
882 | issue_deauth(padapter: adapter, da: pattrib->src, reason: WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); |
883 | ret = RTW_RX_HANDLED; |
884 | goto exit; |
885 | } |
886 | |
887 | exit: |
888 | return ret; |
889 | } |
890 | |
891 | static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_frame *precv_frame) |
892 | { |
893 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
894 | struct sta_priv *pstapriv = &padapter->stapriv; |
895 | u8 *pframe = precv_frame->u.hdr.rx_data; |
896 | struct sta_info *psta = NULL; |
897 | /* uint len = precv_frame->u.hdr.len; */ |
898 | |
899 | if (GetFrameType(pframe) != WIFI_CTRL_TYPE) |
900 | return _FAIL; |
901 | |
902 | /* receive the frames that ra(a1) is my address */ |
903 | if (memcmp(GetAddr1Ptr(pframe), q: myid(peepriv: &padapter->eeprompriv), ETH_ALEN)) |
904 | return _FAIL; |
905 | |
906 | psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); |
907 | if (!psta) |
908 | return _FAIL; |
909 | |
910 | /* for rx pkt statistics */ |
911 | psta->sta_stats.rx_ctrl_pkts++; |
912 | |
913 | /* only handle ps-poll */ |
914 | if (GetFrameSubType(pframe) == WIFI_PSPOLL) { |
915 | u16 aid; |
916 | u8 wmmps_ac = 0; |
917 | |
918 | aid = GetAid(pframe); |
919 | if (psta->aid != aid) |
920 | return _FAIL; |
921 | |
922 | switch (pattrib->priority) { |
923 | case 1: |
924 | case 2: |
925 | wmmps_ac = psta->uapsd_bk&BIT(0); |
926 | break; |
927 | case 4: |
928 | case 5: |
929 | wmmps_ac = psta->uapsd_vi&BIT(0); |
930 | break; |
931 | case 6: |
932 | case 7: |
933 | wmmps_ac = psta->uapsd_vo&BIT(0); |
934 | break; |
935 | case 0: |
936 | case 3: |
937 | default: |
938 | wmmps_ac = psta->uapsd_be&BIT(0); |
939 | break; |
940 | } |
941 | |
942 | if (wmmps_ac) |
943 | return _FAIL; |
944 | |
945 | if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { |
946 | psta->expire_to = pstapriv->expire_to; |
947 | psta->state ^= WIFI_STA_ALIVE_CHK_STATE; |
948 | } |
949 | |
950 | if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) { |
951 | struct list_head *xmitframe_plist, *xmitframe_phead; |
952 | struct xmit_frame *pxmitframe = NULL; |
953 | struct xmit_priv *pxmitpriv = &padapter->xmitpriv; |
954 | |
955 | /* spin_lock_bh(&psta->sleep_q.lock); */ |
956 | spin_lock_bh(lock: &pxmitpriv->lock); |
957 | |
958 | xmitframe_phead = get_list_head(queue: &psta->sleep_q); |
959 | xmitframe_plist = get_next(list: xmitframe_phead); |
960 | |
961 | if (xmitframe_phead != xmitframe_plist) { |
962 | pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); |
963 | |
964 | xmitframe_plist = get_next(list: xmitframe_plist); |
965 | |
966 | list_del_init(entry: &pxmitframe->list); |
967 | |
968 | psta->sleepq_len--; |
969 | |
970 | if (psta->sleepq_len > 0) |
971 | pxmitframe->attrib.mdata = 1; |
972 | else |
973 | pxmitframe->attrib.mdata = 0; |
974 | |
975 | pxmitframe->attrib.triggered = 1; |
976 | |
977 | rtw_hal_xmitframe_enqueue(padapter, pxmitframe); |
978 | |
979 | if (psta->sleepq_len == 0) { |
980 | pstapriv->tim_bitmap &= ~BIT(psta->aid); |
981 | |
982 | /* update BCN for TIM IE */ |
983 | /* update_BCNTIM(padapter); */ |
984 | update_beacon(padapter, ie_id: WLAN_EID_TIM, NULL, tx: true); |
985 | } |
986 | |
987 | /* spin_unlock_bh(&psta->sleep_q.lock); */ |
988 | spin_unlock_bh(lock: &pxmitpriv->lock); |
989 | |
990 | } else { |
991 | /* spin_unlock_bh(&psta->sleep_q.lock); */ |
992 | spin_unlock_bh(lock: &pxmitpriv->lock); |
993 | |
994 | if (pstapriv->tim_bitmap&BIT(psta->aid)) { |
995 | if (psta->sleepq_len == 0) { |
996 | /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ |
997 | issue_nulldata_in_interrupt(padapter, da: psta->hwaddr); |
998 | } else { |
999 | psta->sleepq_len = 0; |
1000 | } |
1001 | |
1002 | pstapriv->tim_bitmap &= ~BIT(psta->aid); |
1003 | |
1004 | /* update BCN for TIM IE */ |
1005 | /* update_BCNTIM(padapter); */ |
1006 | update_beacon(padapter, ie_id: WLAN_EID_TIM, NULL, tx: true); |
1007 | } |
1008 | } |
1009 | } |
1010 | } |
1011 | |
1012 | return _FAIL; |
1013 | |
1014 | } |
1015 | |
1016 | /* perform defrag */ |
1017 | static union recv_frame *recvframe_defrag(struct adapter *adapter, |
1018 | struct __queue *defrag_q) |
1019 | { |
1020 | struct list_head *plist, *phead; |
1021 | u8 wlanhdr_offset; |
1022 | u8 curfragnum; |
1023 | struct recv_frame_hdr *pfhdr, *pnfhdr; |
1024 | union recv_frame *prframe, *pnextrframe; |
1025 | struct __queue *pfree_recv_queue; |
1026 | |
1027 | curfragnum = 0; |
1028 | pfree_recv_queue = &adapter->recvpriv.free_recv_queue; |
1029 | |
1030 | phead = get_list_head(queue: defrag_q); |
1031 | plist = get_next(list: phead); |
1032 | prframe = (union recv_frame *)plist; |
1033 | pfhdr = &prframe->u.hdr; |
1034 | list_del_init(entry: &(prframe->u.list)); |
1035 | |
1036 | if (curfragnum != pfhdr->attrib.frag_num) { |
1037 | /* the first fragment number must be 0 */ |
1038 | /* free the whole queue */ |
1039 | rtw_free_recvframe(precvframe: prframe, pfree_recv_queue); |
1040 | rtw_free_recvframe_queue(pframequeue: defrag_q, pfree_recv_queue); |
1041 | |
1042 | return NULL; |
1043 | } |
1044 | |
1045 | curfragnum++; |
1046 | |
1047 | plist = get_list_head(queue: defrag_q); |
1048 | |
1049 | plist = get_next(list: plist); |
1050 | |
1051 | while (phead != plist) { |
1052 | pnextrframe = (union recv_frame *)plist; |
1053 | pnfhdr = &pnextrframe->u.hdr; |
1054 | |
1055 | |
1056 | /* check the fragment sequence (2nd ~n fragment frame) */ |
1057 | |
1058 | if (curfragnum != pnfhdr->attrib.frag_num) { |
1059 | /* the fragment number must be increasing (after decache) */ |
1060 | /* release the defrag_q & prframe */ |
1061 | rtw_free_recvframe(precvframe: prframe, pfree_recv_queue); |
1062 | rtw_free_recvframe_queue(pframequeue: defrag_q, pfree_recv_queue); |
1063 | return NULL; |
1064 | } |
1065 | |
1066 | curfragnum++; |
1067 | |
1068 | /* copy the 2nd~n fragment frame's payload to the first fragment */ |
1069 | /* get the 2nd~last fragment frame's payload */ |
1070 | |
1071 | wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; |
1072 | |
1073 | recvframe_pull(precvframe: pnextrframe, sz: wlanhdr_offset); |
1074 | |
1075 | /* append to first fragment frame's tail (if privacy frame, pull the ICV) */ |
1076 | recvframe_pull_tail(precvframe: prframe, sz: pfhdr->attrib.icv_len); |
1077 | |
1078 | /* memcpy */ |
1079 | memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); |
1080 | |
1081 | recvframe_put(precvframe: prframe, sz: pnfhdr->len); |
1082 | |
1083 | pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len; |
1084 | plist = get_next(list: plist); |
1085 | |
1086 | } |
1087 | |
1088 | /* free the defrag_q queue and return the prframe */ |
1089 | rtw_free_recvframe_queue(pframequeue: defrag_q, pfree_recv_queue); |
1090 | |
1091 | return prframe; |
1092 | } |
1093 | |
1094 | /* check if need to defrag, if needed queue the frame to defrag_q */ |
1095 | static union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame) |
1096 | { |
1097 | u8 ismfrag; |
1098 | u8 fragnum; |
1099 | u8 *psta_addr; |
1100 | struct recv_frame_hdr *pfhdr; |
1101 | struct sta_info *psta; |
1102 | struct sta_priv *pstapriv; |
1103 | struct list_head *phead; |
1104 | union recv_frame *prtnframe = NULL; |
1105 | struct __queue *pfree_recv_queue, *pdefrag_q; |
1106 | |
1107 | pstapriv = &padapter->stapriv; |
1108 | |
1109 | pfhdr = &precv_frame->u.hdr; |
1110 | |
1111 | pfree_recv_queue = &padapter->recvpriv.free_recv_queue; |
1112 | |
1113 | /* need to define struct of wlan header frame ctrl */ |
1114 | ismfrag = pfhdr->attrib.mfrag; |
1115 | fragnum = pfhdr->attrib.frag_num; |
1116 | |
1117 | psta_addr = pfhdr->attrib.ta; |
1118 | psta = rtw_get_stainfo(pstapriv, hwaddr: psta_addr); |
1119 | if (!psta) { |
1120 | u8 type = GetFrameType(pfhdr->rx_data); |
1121 | |
1122 | if (type != WIFI_DATA_TYPE) { |
1123 | psta = rtw_get_bcmc_stainfo(padapter); |
1124 | pdefrag_q = &psta->sta_recvpriv.defrag_q; |
1125 | } else |
1126 | pdefrag_q = NULL; |
1127 | } else |
1128 | pdefrag_q = &psta->sta_recvpriv.defrag_q; |
1129 | |
1130 | if ((ismfrag == 0) && (fragnum == 0)) |
1131 | prtnframe = precv_frame;/* isn't a fragment frame */ |
1132 | |
1133 | if (ismfrag == 1) { |
1134 | /* 0~(n-1) fragment frame */ |
1135 | /* enqueue to defraf_g */ |
1136 | if (pdefrag_q) { |
1137 | if (fragnum == 0) |
1138 | /* the first fragment */ |
1139 | if (!list_empty(head: &pdefrag_q->queue)) |
1140 | /* free current defrag_q */ |
1141 | rtw_free_recvframe_queue(pframequeue: pdefrag_q, pfree_recv_queue); |
1142 | |
1143 | |
1144 | /* Then enqueue the 0~(n-1) fragment into the defrag_q */ |
1145 | |
1146 | /* spin_lock(&pdefrag_q->lock); */ |
1147 | phead = get_list_head(queue: pdefrag_q); |
1148 | list_add_tail(new: &pfhdr->list, head: phead); |
1149 | /* spin_unlock(&pdefrag_q->lock); */ |
1150 | |
1151 | prtnframe = NULL; |
1152 | |
1153 | } else { |
1154 | /* can't find this ta's defrag_queue, so free this recv_frame */ |
1155 | rtw_free_recvframe(precvframe: precv_frame, pfree_recv_queue); |
1156 | prtnframe = NULL; |
1157 | } |
1158 | |
1159 | } |
1160 | |
1161 | if ((ismfrag == 0) && (fragnum != 0)) { |
1162 | /* the last fragment frame */ |
1163 | /* enqueue the last fragment */ |
1164 | if (pdefrag_q) { |
1165 | /* spin_lock(&pdefrag_q->lock); */ |
1166 | phead = get_list_head(queue: pdefrag_q); |
1167 | list_add_tail(new: &pfhdr->list, head: phead); |
1168 | /* spin_unlock(&pdefrag_q->lock); */ |
1169 | |
1170 | /* call recvframe_defrag to defrag */ |
1171 | precv_frame = recvframe_defrag(adapter: padapter, defrag_q: pdefrag_q); |
1172 | prtnframe = precv_frame; |
1173 | |
1174 | } else { |
1175 | /* can't find this ta's defrag_queue, so free this recv_frame */ |
1176 | rtw_free_recvframe(precvframe: precv_frame, pfree_recv_queue); |
1177 | prtnframe = NULL; |
1178 | } |
1179 | |
1180 | } |
1181 | |
1182 | |
1183 | if ((prtnframe) && (prtnframe->u.hdr.attrib.privacy)) { |
1184 | /* after defrag we must check tkip mic code */ |
1185 | if (recvframe_chkmic(adapter: padapter, precvframe: prtnframe) == _FAIL) { |
1186 | rtw_free_recvframe(precvframe: prtnframe, pfree_recv_queue); |
1187 | prtnframe = NULL; |
1188 | } |
1189 | } |
1190 | return prtnframe; |
1191 | } |
1192 | |
1193 | static signed int validate_recv_mgnt_frame(struct adapter *padapter, union recv_frame *precv_frame) |
1194 | { |
1195 | /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */ |
1196 | |
1197 | precv_frame = recvframe_chk_defrag(padapter, precv_frame); |
1198 | if (!precv_frame) |
1199 | return _SUCCESS; |
1200 | |
1201 | { |
1202 | /* for rx pkt statistics */ |
1203 | struct sta_info *psta = rtw_get_stainfo(pstapriv: &padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data)); |
1204 | |
1205 | if (psta) { |
1206 | psta->sta_stats.rx_mgnt_pkts++; |
1207 | if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON) |
1208 | psta->sta_stats.rx_beacon_pkts++; |
1209 | else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ) |
1210 | psta->sta_stats.rx_probereq_pkts++; |
1211 | else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) { |
1212 | if (!memcmp(p: padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN)) |
1213 | psta->sta_stats.rx_probersp_pkts++; |
1214 | else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)) || |
1215 | is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))) |
1216 | psta->sta_stats.rx_probersp_bm_pkts++; |
1217 | else |
1218 | psta->sta_stats.rx_probersp_uo_pkts++; |
1219 | } |
1220 | } |
1221 | } |
1222 | |
1223 | mgt_dispatcher(padapter, precv_frame); |
1224 | |
1225 | return _SUCCESS; |
1226 | |
1227 | } |
1228 | |
1229 | static signed int validate_recv_data_frame(struct adapter *adapter, union recv_frame *precv_frame) |
1230 | { |
1231 | u8 bretry; |
1232 | u8 *psa, *pda, *pbssid; |
1233 | struct sta_info *psta = NULL; |
1234 | u8 *ptr = precv_frame->u.hdr.rx_data; |
1235 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
1236 | struct security_priv *psecuritypriv = &adapter->securitypriv; |
1237 | signed int ret = _SUCCESS; |
1238 | |
1239 | bretry = GetRetry(ptr); |
1240 | pda = get_da(pframe: ptr); |
1241 | psa = get_sa(pframe: ptr); |
1242 | pbssid = get_hdr_bssid(pframe: ptr); |
1243 | |
1244 | if (!pbssid) { |
1245 | ret = _FAIL; |
1246 | goto exit; |
1247 | } |
1248 | |
1249 | memcpy(pattrib->dst, pda, ETH_ALEN); |
1250 | memcpy(pattrib->src, psa, ETH_ALEN); |
1251 | |
1252 | memcpy(pattrib->bssid, pbssid, ETH_ALEN); |
1253 | |
1254 | switch (pattrib->to_fr_ds) { |
1255 | case 0: |
1256 | memcpy(pattrib->ra, pda, ETH_ALEN); |
1257 | memcpy(pattrib->ta, psa, ETH_ALEN); |
1258 | ret = sta2sta_data_frame(adapter, precv_frame, psta: &psta); |
1259 | break; |
1260 | |
1261 | case 1: |
1262 | memcpy(pattrib->ra, pda, ETH_ALEN); |
1263 | memcpy(pattrib->ta, pbssid, ETH_ALEN); |
1264 | ret = ap2sta_data_frame(adapter, precv_frame, psta: &psta); |
1265 | break; |
1266 | |
1267 | case 2: |
1268 | memcpy(pattrib->ra, pbssid, ETH_ALEN); |
1269 | memcpy(pattrib->ta, psa, ETH_ALEN); |
1270 | ret = sta2ap_data_frame(adapter, precv_frame, psta: &psta); |
1271 | break; |
1272 | |
1273 | case 3: |
1274 | memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); |
1275 | memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); |
1276 | ret = _FAIL; |
1277 | break; |
1278 | |
1279 | default: |
1280 | ret = _FAIL; |
1281 | break; |
1282 | |
1283 | } |
1284 | |
1285 | if (ret == _FAIL) { |
1286 | goto exit; |
1287 | } else if (ret == RTW_RX_HANDLED) { |
1288 | goto exit; |
1289 | } |
1290 | |
1291 | |
1292 | if (!psta) { |
1293 | ret = _FAIL; |
1294 | goto exit; |
1295 | } |
1296 | |
1297 | /* psta->rssi = prxcmd->rssi; */ |
1298 | /* psta->signal_quality = prxcmd->sq; */ |
1299 | precv_frame->u.hdr.psta = psta; |
1300 | |
1301 | |
1302 | pattrib->amsdu = 0; |
1303 | pattrib->ack_policy = 0; |
1304 | /* parsing QC field */ |
1305 | if (pattrib->qos == 1) { |
1306 | pattrib->priority = GetPriority((ptr + 24)); |
1307 | pattrib->ack_policy = GetAckpolicy((ptr + 24)); |
1308 | pattrib->amsdu = GetAMsdu((ptr + 24)); |
1309 | pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26; |
1310 | |
1311 | if (pattrib->priority != 0 && pattrib->priority != 3) |
1312 | adapter->recvpriv.bIsAnyNonBEPkts = true; |
1313 | |
1314 | } else { |
1315 | pattrib->priority = 0; |
1316 | pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 30 : 24; |
1317 | } |
1318 | |
1319 | |
1320 | if (pattrib->order)/* HT-CTRL 11n */ |
1321 | pattrib->hdrlen += 4; |
1322 | |
1323 | precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; |
1324 | |
1325 | /* decache, drop duplicate recv packets */ |
1326 | if (recv_decache(precv_frame, bretry, prxcache: &psta->sta_recvpriv.rxcache) == _FAIL) { |
1327 | ret = _FAIL; |
1328 | goto exit; |
1329 | } |
1330 | |
1331 | if (pattrib->privacy) { |
1332 | GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, is_multicast_ether_addr(pattrib->ra)); |
1333 | |
1334 | SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); |
1335 | } else { |
1336 | pattrib->encrypt = 0; |
1337 | pattrib->iv_len = pattrib->icv_len = 0; |
1338 | } |
1339 | |
1340 | exit: |
1341 | return ret; |
1342 | } |
1343 | |
1344 | static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame *precv_frame) |
1345 | { |
1346 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
1347 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
1348 | u8 *ptr = precv_frame->u.hdr.rx_data; |
1349 | u8 subtype; |
1350 | |
1351 | subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */ |
1352 | |
1353 | /* only support station mode */ |
1354 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) && |
1355 | adapter->securitypriv.binstallBIPkey == true) { |
1356 | /* unicast management frame decrypt */ |
1357 | if (pattrib->privacy && !(is_multicast_ether_addr(GetAddr1Ptr(ptr))) && |
1358 | (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) { |
1359 | u8 *mgmt_DATA; |
1360 | u32 data_len = 0; |
1361 | |
1362 | pattrib->bdecrypted = 0; |
1363 | pattrib->encrypt = _AES_; |
1364 | pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); |
1365 | /* set iv and icv length */ |
1366 | SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); |
1367 | memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); |
1368 | memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); |
1369 | /* actual management data frame body */ |
1370 | data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; |
1371 | mgmt_DATA = rtw_zmalloc(data_len); |
1372 | if (!mgmt_DATA) |
1373 | goto validate_80211w_fail; |
1374 | precv_frame = decryptor(padapter: adapter, precv_frame); |
1375 | /* save actual management data frame body */ |
1376 | memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len); |
1377 | /* overwrite the iv field */ |
1378 | memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len); |
1379 | /* remove the iv and icv length */ |
1380 | pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len; |
1381 | kfree(objp: mgmt_DATA); |
1382 | if (!precv_frame) |
1383 | goto validate_80211w_fail; |
1384 | } else if (is_multicast_ether_addr(GetAddr1Ptr(ptr)) && |
1385 | (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) { |
1386 | signed int BIP_ret = _SUCCESS; |
1387 | /* verify BIP MME IE of broadcast/multicast de-auth/disassoc packet */ |
1388 | BIP_ret = rtw_BIP_verify(padapter: adapter, precvframe: (u8 *)precv_frame); |
1389 | if (BIP_ret == _FAIL) { |
1390 | goto validate_80211w_fail; |
1391 | } else if (BIP_ret == RTW_RX_HANDLED) { |
1392 | /* issue sa query request */ |
1393 | issue_action_SA_Query(padapter: adapter, NULL, action: 0, tid: 0); |
1394 | goto validate_80211w_fail; |
1395 | } |
1396 | } else { /* 802.11w protect */ |
1397 | if (subtype == WIFI_ACTION) { |
1398 | /* according 802.11-2012 standard, these five types are not robust types */ |
1399 | if (ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC && |
1400 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT && |
1401 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM && |
1402 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED && |
1403 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) { |
1404 | goto validate_80211w_fail; |
1405 | } |
1406 | } else if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) { |
1407 | /* issue sa query request */ |
1408 | issue_action_SA_Query(padapter: adapter, NULL, action: 0, tid: 0); |
1409 | goto validate_80211w_fail; |
1410 | } |
1411 | } |
1412 | } |
1413 | return _SUCCESS; |
1414 | |
1415 | validate_80211w_fail: |
1416 | return _FAIL; |
1417 | |
1418 | } |
1419 | |
1420 | static signed int validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame) |
1421 | { |
1422 | /* shall check frame subtype, to / from ds, da, bssid */ |
1423 | |
1424 | /* then call check if rx seq/frag. duplicated. */ |
1425 | |
1426 | u8 type; |
1427 | u8 subtype; |
1428 | signed int retval = _SUCCESS; |
1429 | u8 bDumpRxPkt; |
1430 | |
1431 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; |
1432 | |
1433 | u8 *ptr = precv_frame->u.hdr.rx_data; |
1434 | u8 ver = (unsigned char) (*ptr)&0x3; |
1435 | |
1436 | /* add version chk */ |
1437 | if (ver != 0) { |
1438 | retval = _FAIL; |
1439 | goto exit; |
1440 | } |
1441 | |
1442 | type = GetFrameType(ptr); |
1443 | subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */ |
1444 | |
1445 | pattrib->to_fr_ds = get_tofr_ds(ptr); |
1446 | |
1447 | pattrib->frag_num = GetFragNum(ptr); |
1448 | pattrib->seq_num = GetSequence(ptr); |
1449 | |
1450 | pattrib->pw_save = GetPwrMgt(ptr); |
1451 | pattrib->mfrag = GetMFrag(ptr); |
1452 | pattrib->mdata = GetMData(ptr); |
1453 | pattrib->privacy = GetPrivacy(ptr); |
1454 | pattrib->order = GetOrder(ptr); |
1455 | rtw_hal_get_def_var(padapter: adapter, eVariable: HAL_DEF_DBG_DUMP_RXPKT, pValue: &(bDumpRxPkt)); |
1456 | |
1457 | switch (type) { |
1458 | case WIFI_MGT_TYPE: /* mgnt */ |
1459 | if (validate_80211w_mgmt(adapter, precv_frame) == _FAIL) { |
1460 | retval = _FAIL; |
1461 | break; |
1462 | } |
1463 | |
1464 | retval = validate_recv_mgnt_frame(padapter: adapter, precv_frame); |
1465 | retval = _FAIL; /* only data frame return _SUCCESS */ |
1466 | break; |
1467 | case WIFI_CTRL_TYPE: /* ctrl */ |
1468 | retval = validate_recv_ctrl_frame(padapter: adapter, precv_frame); |
1469 | retval = _FAIL; /* only data frame return _SUCCESS */ |
1470 | break; |
1471 | case WIFI_DATA_TYPE: /* data */ |
1472 | pattrib->qos = (subtype & BIT(7)) ? 1:0; |
1473 | retval = validate_recv_data_frame(adapter, precv_frame); |
1474 | if (retval == _FAIL) { |
1475 | struct recv_priv *precvpriv = &adapter->recvpriv; |
1476 | |
1477 | precvpriv->rx_drop++; |
1478 | } else if (retval == _SUCCESS) { |
1479 | #ifdef DBG_RX_DUMP_EAP |
1480 | u8 bDumpRxPkt; |
1481 | u16 eth_type; |
1482 | |
1483 | /* dump eapol */ |
1484 | rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt)); |
1485 | /* get ether_type */ |
1486 | memcpy(ð_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_LENGTH, 2); |
1487 | eth_type = ntohs((unsigned short) eth_type); |
1488 | #endif |
1489 | } |
1490 | break; |
1491 | default: |
1492 | retval = _FAIL; |
1493 | break; |
1494 | } |
1495 | |
1496 | exit: |
1497 | return retval; |
1498 | } |
1499 | |
1500 | /* remove the wlanhdr and add the eth_hdr */ |
1501 | static signed int wlanhdr_to_ethhdr(union recv_frame *precvframe) |
1502 | { |
1503 | signed int rmv_len; |
1504 | u16 eth_type, len; |
1505 | u8 bsnaphdr; |
1506 | u8 *psnap_type; |
1507 | struct ieee80211_snap_hdr *psnap; |
1508 | __be16 be_tmp; |
1509 | struct adapter *adapter = precvframe->u.hdr.adapter; |
1510 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; |
1511 | u8 *ptr = precvframe->u.hdr.rx_data; /* point to frame_ctrl field */ |
1512 | struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib; |
1513 | |
1514 | if (pattrib->encrypt) |
1515 | recvframe_pull_tail(precvframe, sz: pattrib->icv_len); |
1516 | |
1517 | psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len); |
1518 | psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; |
1519 | /* convert hdr + possible LLC headers into Ethernet header */ |
1520 | /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */ |
1521 | if ((!memcmp(p: psnap, q: rfc1042_header, SNAP_SIZE) && |
1522 | (memcmp(p: psnap_type, q: SNAP_ETH_TYPE_IPX, size: 2)) && |
1523 | (memcmp(p: psnap_type, q: SNAP_ETH_TYPE_APPLETALK_AARP, size: 2))) || |
1524 | /* eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || */ |
1525 | !memcmp(p: psnap, q: bridge_tunnel_header, SNAP_SIZE)) { |
1526 | /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ |
1527 | bsnaphdr = true; |
1528 | } else |
1529 | /* Leave Ethernet header part of hdr and full payload */ |
1530 | bsnaphdr = false; |
1531 | |
1532 | rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr?SNAP_SIZE:0); |
1533 | len = precvframe->u.hdr.len - rmv_len; |
1534 | |
1535 | memcpy(&be_tmp, ptr+rmv_len, 2); |
1536 | eth_type = ntohs(be_tmp); /* pattrib->ether_type */ |
1537 | pattrib->eth_type = eth_type; |
1538 | |
1539 | if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) { |
1540 | ptr += rmv_len; |
1541 | *ptr = 0x87; |
1542 | *(ptr+1) = 0x12; |
1543 | |
1544 | eth_type = 0x8712; |
1545 | /* append rx status for mp test packets */ |
1546 | ptr = recvframe_pull(precvframe, sz: (rmv_len-sizeof(struct ethhdr)+2)-24); |
1547 | if (!ptr) |
1548 | return _FAIL; |
1549 | memcpy(ptr, get_rxmem(precvframe), 24); |
1550 | ptr += 24; |
1551 | } else { |
1552 | ptr = recvframe_pull(precvframe, sz: (rmv_len-sizeof(struct ethhdr) + (bsnaphdr?2:0))); |
1553 | if (!ptr) |
1554 | return _FAIL; |
1555 | } |
1556 | |
1557 | memcpy(ptr, pattrib->dst, ETH_ALEN); |
1558 | memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN); |
1559 | |
1560 | if (!bsnaphdr) { |
1561 | be_tmp = htons(len); |
1562 | memcpy(ptr+12, &be_tmp, 2); |
1563 | } |
1564 | |
1565 | return _SUCCESS; |
1566 | } |
1567 | |
1568 | static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe) |
1569 | { |
1570 | int a_len, padding_len; |
1571 | u16 nSubframe_Length; |
1572 | u8 nr_subframes, i; |
1573 | u8 *pdata; |
1574 | struct sk_buff *sub_pkt, *subframes[MAX_SUBFRAME_COUNT]; |
1575 | struct recv_priv *precvpriv = &padapter->recvpriv; |
1576 | struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue); |
1577 | |
1578 | nr_subframes = 0; |
1579 | |
1580 | recvframe_pull(precvframe: prframe, sz: prframe->u.hdr.attrib.hdrlen); |
1581 | |
1582 | if (prframe->u.hdr.attrib.iv_len > 0) |
1583 | recvframe_pull(precvframe: prframe, sz: prframe->u.hdr.attrib.iv_len); |
1584 | |
1585 | a_len = prframe->u.hdr.len; |
1586 | |
1587 | pdata = prframe->u.hdr.rx_data; |
1588 | |
1589 | while (a_len > ETH_HLEN) { |
1590 | |
1591 | /* Offset 12 denote 2 mac address */ |
1592 | nSubframe_Length = get_unaligned_be16(p: pdata + 12); |
1593 | |
1594 | if (a_len < ETH_HLEN + nSubframe_Length) |
1595 | break; |
1596 | |
1597 | sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata); |
1598 | if (!sub_pkt) |
1599 | break; |
1600 | |
1601 | /* move the data point to data content */ |
1602 | pdata += ETH_HLEN; |
1603 | a_len -= ETH_HLEN; |
1604 | |
1605 | subframes[nr_subframes++] = sub_pkt; |
1606 | |
1607 | if (nr_subframes >= MAX_SUBFRAME_COUNT) |
1608 | break; |
1609 | |
1610 | pdata += nSubframe_Length; |
1611 | a_len -= nSubframe_Length; |
1612 | if (a_len != 0) { |
1613 | padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1)); |
1614 | if (padding_len == 4) |
1615 | padding_len = 0; |
1616 | |
1617 | if (a_len < padding_len) |
1618 | break; |
1619 | |
1620 | pdata += padding_len; |
1621 | a_len -= padding_len; |
1622 | } |
1623 | } |
1624 | |
1625 | for (i = 0; i < nr_subframes; i++) { |
1626 | sub_pkt = subframes[i]; |
1627 | |
1628 | /* Indicate the packets to upper layer */ |
1629 | if (sub_pkt) |
1630 | rtw_os_recv_indicate_pkt(padapter, pkt: sub_pkt, pattrib: &prframe->u.hdr.attrib); |
1631 | } |
1632 | |
1633 | prframe->u.hdr.len = 0; |
1634 | rtw_free_recvframe(precvframe: prframe, pfree_recv_queue);/* free this recv_frame */ |
1635 | |
1636 | return _SUCCESS; |
1637 | } |
1638 | |
1639 | static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) |
1640 | { |
1641 | struct adapter *padapter = preorder_ctrl->padapter; |
1642 | struct dvobj_priv *psdpriv = padapter->dvobj; |
1643 | struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; |
1644 | u8 wsize = preorder_ctrl->wsize_b; |
1645 | u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF;/* 4096; */ |
1646 | |
1647 | /* Rx Reorder initialize condition. */ |
1648 | if (preorder_ctrl->indicate_seq == 0xFFFF) |
1649 | preorder_ctrl->indicate_seq = seq_num; |
1650 | |
1651 | /* Drop out the packet which SeqNum is smaller than WinStart */ |
1652 | if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) |
1653 | return false; |
1654 | |
1655 | /* */ |
1656 | /* Sliding window manipulation. Conditions includes: */ |
1657 | /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */ |
1658 | /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ |
1659 | /* */ |
1660 | if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) { |
1661 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; |
1662 | |
1663 | } else if (SN_LESS(wend, seq_num)) { |
1664 | /* boundary situation, when seq_num cross 0xFFF */ |
1665 | if (seq_num >= (wsize - 1)) |
1666 | preorder_ctrl->indicate_seq = seq_num + 1 - wsize; |
1667 | else |
1668 | preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; |
1669 | pdbgpriv->dbg_rx_ampdu_window_shift_cnt++; |
1670 | } |
1671 | |
1672 | return true; |
1673 | } |
1674 | |
1675 | static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe) |
1676 | { |
1677 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; |
1678 | struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; |
1679 | struct list_head *phead, *plist; |
1680 | union recv_frame *pnextrframe; |
1681 | struct rx_pkt_attrib *pnextattrib; |
1682 | |
1683 | /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */ |
1684 | /* spin_lock(&ppending_recvframe_queue->lock); */ |
1685 | |
1686 | |
1687 | phead = get_list_head(queue: ppending_recvframe_queue); |
1688 | plist = get_next(list: phead); |
1689 | |
1690 | while (phead != plist) { |
1691 | pnextrframe = (union recv_frame *)plist; |
1692 | pnextattrib = &pnextrframe->u.hdr.attrib; |
1693 | |
1694 | if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) |
1695 | plist = get_next(list: plist); |
1696 | else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) |
1697 | /* Duplicate entry is found!! Do not insert current entry. */ |
1698 | /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ |
1699 | return false; |
1700 | else |
1701 | break; |
1702 | |
1703 | } |
1704 | |
1705 | |
1706 | /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */ |
1707 | /* spin_lock(&ppending_recvframe_queue->lock); */ |
1708 | |
1709 | list_del_init(entry: &(prframe->u.hdr.list)); |
1710 | |
1711 | list_add_tail(new: &(prframe->u.hdr.list), head: plist); |
1712 | |
1713 | /* spin_unlock(&ppending_recvframe_queue->lock); */ |
1714 | /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ |
1715 | |
1716 | return true; |
1717 | |
1718 | } |
1719 | |
1720 | static void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq) |
1721 | { |
1722 | if (current_seq < prev_seq) |
1723 | pdbgpriv->dbg_rx_ampdu_loss_count += (4096 + current_seq - prev_seq); |
1724 | else |
1725 | pdbgpriv->dbg_rx_ampdu_loss_count += (current_seq - prev_seq); |
1726 | |
1727 | } |
1728 | |
1729 | static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced) |
1730 | { |
1731 | struct list_head *phead, *plist; |
1732 | union recv_frame *prframe; |
1733 | struct rx_pkt_attrib *pattrib; |
1734 | /* u8 index = 0; */ |
1735 | int bPktInBuf = false; |
1736 | struct recv_priv *precvpriv = &padapter->recvpriv; |
1737 | struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; |
1738 | struct dvobj_priv *psdpriv = padapter->dvobj; |
1739 | struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; |
1740 | |
1741 | /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */ |
1742 | /* spin_lock(&ppending_recvframe_queue->lock); */ |
1743 | |
1744 | phead = get_list_head(queue: ppending_recvframe_queue); |
1745 | plist = get_next(list: phead); |
1746 | |
1747 | /* Handling some condition for forced indicate case. */ |
1748 | if (bforced == true) { |
1749 | pdbgpriv->dbg_rx_ampdu_forced_indicate_count++; |
1750 | if (list_empty(head: phead)) { |
1751 | /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ |
1752 | /* spin_unlock(&ppending_recvframe_queue->lock); */ |
1753 | return true; |
1754 | } |
1755 | |
1756 | prframe = (union recv_frame *)plist; |
1757 | pattrib = &prframe->u.hdr.attrib; |
1758 | |
1759 | recv_indicatepkts_pkt_loss_cnt(pdbgpriv, prev_seq: preorder_ctrl->indicate_seq, current_seq: pattrib->seq_num); |
1760 | preorder_ctrl->indicate_seq = pattrib->seq_num; |
1761 | |
1762 | } |
1763 | |
1764 | /* Prepare indication list and indication. */ |
1765 | /* Check if there is any packet need indicate. */ |
1766 | while (!list_empty(head: phead)) { |
1767 | |
1768 | prframe = (union recv_frame *)plist; |
1769 | pattrib = &prframe->u.hdr.attrib; |
1770 | |
1771 | if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { |
1772 | plist = get_next(list: plist); |
1773 | list_del_init(entry: &(prframe->u.hdr.list)); |
1774 | |
1775 | if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) |
1776 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; |
1777 | |
1778 | /* Set this as a lock to make sure that only one thread is indicating packet. */ |
1779 | /* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */ |
1780 | |
1781 | /* Indicate packets */ |
1782 | |
1783 | /* indicate this recv_frame */ |
1784 | if (!pattrib->amsdu) { |
1785 | if ((padapter->bDriverStopped == false) && |
1786 | (padapter->bSurpriseRemoved == false)) |
1787 | rtw_recv_indicatepkt(adapter: padapter, precv_frame: prframe);/* indicate this recv_frame */ |
1788 | |
1789 | } else if (pattrib->amsdu == 1) { |
1790 | if (amsdu_to_msdu(padapter, prframe) != _SUCCESS) |
1791 | rtw_free_recvframe(precvframe: prframe, pfree_recv_queue: &precvpriv->free_recv_queue); |
1792 | |
1793 | } else { |
1794 | /* error condition; */ |
1795 | } |
1796 | |
1797 | |
1798 | /* Update local variables. */ |
1799 | bPktInBuf = false; |
1800 | |
1801 | } else { |
1802 | bPktInBuf = true; |
1803 | break; |
1804 | } |
1805 | |
1806 | } |
1807 | |
1808 | /* spin_unlock(&ppending_recvframe_queue->lock); */ |
1809 | /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ |
1810 | |
1811 | return bPktInBuf; |
1812 | } |
1813 | |
1814 | static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe) |
1815 | { |
1816 | int retval = _SUCCESS; |
1817 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; |
1818 | struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl; |
1819 | struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; |
1820 | struct dvobj_priv *psdpriv = padapter->dvobj; |
1821 | struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; |
1822 | |
1823 | if (!pattrib->amsdu) { |
1824 | /* s1. */ |
1825 | wlanhdr_to_ethhdr(precvframe: prframe); |
1826 | |
1827 | if (pattrib->qos != 1) { |
1828 | if ((padapter->bDriverStopped == false) && |
1829 | (padapter->bSurpriseRemoved == false)) { |
1830 | rtw_recv_indicatepkt(adapter: padapter, precv_frame: prframe); |
1831 | return _SUCCESS; |
1832 | |
1833 | } |
1834 | |
1835 | return _FAIL; |
1836 | |
1837 | } |
1838 | |
1839 | if (preorder_ctrl->enable == false) { |
1840 | /* indicate this recv_frame */ |
1841 | preorder_ctrl->indicate_seq = pattrib->seq_num; |
1842 | |
1843 | rtw_recv_indicatepkt(adapter: padapter, precv_frame: prframe); |
1844 | |
1845 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096; |
1846 | |
1847 | return _SUCCESS; |
1848 | } |
1849 | } else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */ |
1850 | if (preorder_ctrl->enable == false) { |
1851 | preorder_ctrl->indicate_seq = pattrib->seq_num; |
1852 | |
1853 | retval = amsdu_to_msdu(padapter, prframe); |
1854 | |
1855 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096; |
1856 | |
1857 | if (retval != _SUCCESS) { |
1858 | } |
1859 | |
1860 | return retval; |
1861 | } |
1862 | } |
1863 | |
1864 | spin_lock_bh(lock: &ppending_recvframe_queue->lock); |
1865 | |
1866 | /* s2. check if winstart_b(indicate_seq) needs to been updated */ |
1867 | if (!check_indicate_seq(preorder_ctrl, seq_num: pattrib->seq_num)) { |
1868 | pdbgpriv->dbg_rx_ampdu_drop_count++; |
1869 | goto _err_exit; |
1870 | } |
1871 | |
1872 | |
1873 | /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ |
1874 | if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) { |
1875 | /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ |
1876 | /* return _FAIL; */ |
1877 | goto _err_exit; |
1878 | } |
1879 | |
1880 | |
1881 | /* s4. */ |
1882 | /* Indication process. */ |
1883 | /* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */ |
1884 | /* with the SeqNum smaller than latest WinStart and buffer other packets. */ |
1885 | /* */ |
1886 | /* For Rx Reorder condition: */ |
1887 | /* 1. All packets with SeqNum smaller than WinStart => Indicate */ |
1888 | /* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */ |
1889 | /* */ |
1890 | |
1891 | /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */ |
1892 | if (recv_indicatepkts_in_order(padapter, preorder_ctrl, bforced: false) == true) { |
1893 | _set_timer(ptimer: &preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); |
1894 | spin_unlock_bh(lock: &ppending_recvframe_queue->lock); |
1895 | } else { |
1896 | spin_unlock_bh(lock: &ppending_recvframe_queue->lock); |
1897 | del_timer_sync(timer: &preorder_ctrl->reordering_ctrl_timer); |
1898 | } |
1899 | |
1900 | return _SUCCESS; |
1901 | |
1902 | _err_exit: |
1903 | spin_unlock_bh(lock: &ppending_recvframe_queue->lock); |
1904 | |
1905 | return _FAIL; |
1906 | } |
1907 | |
1908 | |
1909 | void rtw_reordering_ctrl_timeout_handler(struct timer_list *t) |
1910 | { |
1911 | struct recv_reorder_ctrl *preorder_ctrl = |
1912 | from_timer(preorder_ctrl, t, reordering_ctrl_timer); |
1913 | struct adapter *padapter = preorder_ctrl->padapter; |
1914 | struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; |
1915 | |
1916 | |
1917 | if (padapter->bDriverStopped || padapter->bSurpriseRemoved) |
1918 | return; |
1919 | |
1920 | spin_lock_bh(lock: &ppending_recvframe_queue->lock); |
1921 | |
1922 | if (recv_indicatepkts_in_order(padapter, preorder_ctrl, bforced: true) == true) |
1923 | _set_timer(ptimer: &preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); |
1924 | |
1925 | spin_unlock_bh(lock: &ppending_recvframe_queue->lock); |
1926 | |
1927 | } |
1928 | |
1929 | static int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe) |
1930 | { |
1931 | int retval = _SUCCESS; |
1932 | /* struct recv_priv *precvpriv = &padapter->recvpriv; */ |
1933 | /* struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; */ |
1934 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
1935 | struct ht_priv *phtpriv = &pmlmepriv->htpriv; |
1936 | |
1937 | if (phtpriv->ht_option == true) { /* B/G/N Mode */ |
1938 | /* prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */ |
1939 | |
1940 | if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { /* including perform A-MPDU Rx Ordering Buffer Control */ |
1941 | |
1942 | if ((padapter->bDriverStopped == false) && |
1943 | (padapter->bSurpriseRemoved == false)) { |
1944 | retval = _FAIL; |
1945 | return retval; |
1946 | } |
1947 | } |
1948 | } else { /* B/G mode */ |
1949 | retval = wlanhdr_to_ethhdr(precvframe: prframe); |
1950 | if (retval != _SUCCESS) |
1951 | return retval; |
1952 | |
1953 | if ((padapter->bDriverStopped == false) && (padapter->bSurpriseRemoved == false)) { |
1954 | /* indicate this recv_frame */ |
1955 | rtw_recv_indicatepkt(adapter: padapter, precv_frame: prframe); |
1956 | } else { |
1957 | retval = _FAIL; |
1958 | return retval; |
1959 | } |
1960 | |
1961 | } |
1962 | |
1963 | return retval; |
1964 | |
1965 | } |
1966 | |
1967 | static int recv_func_prehandle(struct adapter *padapter, union recv_frame *rframe) |
1968 | { |
1969 | int ret = _SUCCESS; |
1970 | struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; |
1971 | |
1972 | /* check the frame crtl field and decache */ |
1973 | ret = validate_recv_frame(adapter: padapter, precv_frame: rframe); |
1974 | if (ret != _SUCCESS) { |
1975 | rtw_free_recvframe(precvframe: rframe, pfree_recv_queue);/* free this recv_frame */ |
1976 | goto exit; |
1977 | } |
1978 | |
1979 | exit: |
1980 | return ret; |
1981 | } |
1982 | |
1983 | static int recv_func_posthandle(struct adapter *padapter, union recv_frame *prframe) |
1984 | { |
1985 | int ret = _SUCCESS; |
1986 | union recv_frame *orig_prframe = prframe; |
1987 | struct recv_priv *precvpriv = &padapter->recvpriv; |
1988 | struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; |
1989 | |
1990 | prframe = decryptor(padapter, precv_frame: prframe); |
1991 | if (!prframe) { |
1992 | ret = _FAIL; |
1993 | goto _recv_data_drop; |
1994 | } |
1995 | |
1996 | prframe = recvframe_chk_defrag(padapter, precv_frame: prframe); |
1997 | if (!prframe) |
1998 | goto _recv_data_drop; |
1999 | |
2000 | prframe = portctrl(adapter: padapter, precv_frame: prframe); |
2001 | if (!prframe) { |
2002 | ret = _FAIL; |
2003 | goto _recv_data_drop; |
2004 | } |
2005 | |
2006 | count_rx_stats(padapter, prframe, NULL); |
2007 | |
2008 | ret = process_recv_indicatepkts(padapter, prframe); |
2009 | if (ret != _SUCCESS) { |
2010 | rtw_free_recvframe(precvframe: orig_prframe, pfree_recv_queue);/* free this recv_frame */ |
2011 | goto _recv_data_drop; |
2012 | } |
2013 | |
2014 | _recv_data_drop: |
2015 | precvpriv->rx_drop++; |
2016 | return ret; |
2017 | } |
2018 | |
2019 | static int recv_func(struct adapter *padapter, union recv_frame *rframe) |
2020 | { |
2021 | int ret; |
2022 | struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib; |
2023 | struct recv_priv *recvpriv = &padapter->recvpriv; |
2024 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
2025 | struct mlme_priv *mlmepriv = &padapter->mlmepriv; |
2026 | |
2027 | /* check if need to handle uc_swdec_pending_queue*/ |
2028 | if (check_fwstate(pmlmepriv: mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) { |
2029 | union recv_frame *pending_frame; |
2030 | int cnt = 0; |
2031 | |
2032 | while ((pending_frame = rtw_alloc_recvframe(pfree_recv_queue: &padapter->recvpriv.uc_swdec_pending_queue))) { |
2033 | cnt++; |
2034 | recv_func_posthandle(padapter, prframe: pending_frame); |
2035 | } |
2036 | } |
2037 | |
2038 | ret = recv_func_prehandle(padapter, rframe); |
2039 | |
2040 | if (ret == _SUCCESS) { |
2041 | |
2042 | /* check if need to enqueue into uc_swdec_pending_queue*/ |
2043 | if (check_fwstate(pmlmepriv: mlmepriv, WIFI_STATION_STATE) && |
2044 | !is_multicast_ether_addr(addr: prxattrib->ra) && prxattrib->encrypt > 0 && |
2045 | (prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt == true) && |
2046 | psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK && |
2047 | !psecuritypriv->busetkipkey) { |
2048 | rtw_enqueue_recvframe(precvframe: rframe, queue: &padapter->recvpriv.uc_swdec_pending_queue); |
2049 | |
2050 | if (recvpriv->free_recvframe_cnt < NR_RECVFRAME/4) { |
2051 | /* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt */ |
2052 | rframe = rtw_alloc_recvframe(pfree_recv_queue: &padapter->recvpriv.uc_swdec_pending_queue); |
2053 | if (rframe) |
2054 | goto do_posthandle; |
2055 | } |
2056 | goto exit; |
2057 | } |
2058 | |
2059 | do_posthandle: |
2060 | ret = recv_func_posthandle(padapter, prframe: rframe); |
2061 | } |
2062 | |
2063 | exit: |
2064 | return ret; |
2065 | } |
2066 | |
2067 | |
2068 | s32 rtw_recv_entry(union recv_frame *precvframe) |
2069 | { |
2070 | struct adapter *padapter; |
2071 | struct recv_priv *precvpriv; |
2072 | s32 ret = _SUCCESS; |
2073 | |
2074 | padapter = precvframe->u.hdr.adapter; |
2075 | |
2076 | precvpriv = &padapter->recvpriv; |
2077 | |
2078 | ret = recv_func(padapter, rframe: precvframe); |
2079 | if (ret == _FAIL) |
2080 | goto _recv_entry_drop; |
2081 | |
2082 | precvpriv->rx_pkts++; |
2083 | |
2084 | return ret; |
2085 | |
2086 | _recv_entry_drop: |
2087 | |
2088 | return ret; |
2089 | } |
2090 | |
2091 | static void rtw_signal_stat_timer_hdl(struct timer_list *t) |
2092 | { |
2093 | struct adapter *adapter = |
2094 | from_timer(adapter, t, recvpriv.signal_stat_timer); |
2095 | struct recv_priv *recvpriv = &adapter->recvpriv; |
2096 | |
2097 | u32 tmp_s, tmp_q; |
2098 | u8 avg_signal_strength = 0; |
2099 | u8 avg_signal_qual = 0; |
2100 | u32 num_signal_strength = 0; |
2101 | u32 __maybe_unused num_signal_qual = 0; |
2102 | u8 _alpha = 5; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */ |
2103 | |
2104 | if (adapter->recvpriv.is_signal_dbg) { |
2105 | /* update the user specific value, signal_strength_dbg, to signal_strength, rssi */ |
2106 | adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg; |
2107 | adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm(SignalStrengthIndex: (u8)adapter->recvpriv.signal_strength_dbg); |
2108 | } else { |
2109 | |
2110 | if (recvpriv->signal_strength_data.update_req == 0) {/* update_req is clear, means we got rx */ |
2111 | avg_signal_strength = recvpriv->signal_strength_data.avg_val; |
2112 | num_signal_strength = recvpriv->signal_strength_data.total_num; |
2113 | /* after avg_vals are acquired, we can re-stat the signal values */ |
2114 | recvpriv->signal_strength_data.update_req = 1; |
2115 | } |
2116 | |
2117 | if (recvpriv->signal_qual_data.update_req == 0) {/* update_req is clear, means we got rx */ |
2118 | avg_signal_qual = recvpriv->signal_qual_data.avg_val; |
2119 | num_signal_qual = recvpriv->signal_qual_data.total_num; |
2120 | /* after avg_vals are acquired, we can re-stat the signal values */ |
2121 | recvpriv->signal_qual_data.update_req = 1; |
2122 | } |
2123 | |
2124 | if (num_signal_strength == 0) { |
2125 | if (rtw_get_on_cur_ch_time(adapter) == 0 || |
2126 | jiffies_to_msecs(j: jiffies - rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval |
2127 | ) { |
2128 | goto set_timer; |
2129 | } |
2130 | } |
2131 | |
2132 | if (check_fwstate(pmlmepriv: &adapter->mlmepriv, _FW_UNDER_SURVEY) == true || |
2133 | check_fwstate(pmlmepriv: &adapter->mlmepriv, _FW_LINKED) == false |
2134 | ) { |
2135 | goto set_timer; |
2136 | } |
2137 | |
2138 | /* update value of signal_strength, rssi, signal_qual */ |
2139 | tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); |
2140 | if (tmp_s % _alpha) |
2141 | tmp_s = tmp_s/_alpha + 1; |
2142 | else |
2143 | tmp_s = tmp_s/_alpha; |
2144 | if (tmp_s > 100) |
2145 | tmp_s = 100; |
2146 | |
2147 | tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); |
2148 | if (tmp_q % _alpha) |
2149 | tmp_q = tmp_q/_alpha + 1; |
2150 | else |
2151 | tmp_q = tmp_q/_alpha; |
2152 | if (tmp_q > 100) |
2153 | tmp_q = 100; |
2154 | |
2155 | recvpriv->signal_strength = tmp_s; |
2156 | recvpriv->rssi = (s8)translate_percentage_to_dbm(SignalStrengthIndex: tmp_s); |
2157 | recvpriv->signal_qual = tmp_q; |
2158 | } |
2159 | |
2160 | set_timer: |
2161 | rtw_set_signal_stat_timer(recvpriv); |
2162 | |
2163 | } |
2164 | |