1 /******************************************************************************
2 *
3 * Copyright(c) 2016 - 2017 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 *****************************************************************************/
15 #define _RTL8821CS_RECV_C_
16
17 #include <drv_types.h> /* PADAPTER and etc. */
18 #include <hal_data.h> /* HAL_DATA_TYPE */
19 #include "../../hal_halmac.h" /* BIT_ACRC32_8821C and etc. */
20 #include "../rtl8821c.h" /* rtl8821c_rxdesc2attribute(), rtl8821c_c2h_handler_no_io() */
21 #include "rtl8821cs_recv.h" /* MAX_RECVBUF_SZ */
22
23 #if 0
24 /*
25 * Return:
26 * Pointer of _pkt, otherwise NULL.
27 */
28 static _pkt *alloc_recvbuf_skb(struct recv_buf *recvbuf, u32 size)
29 {
30 _pkt *skb;
31 u32 alignsz = RECVBUFF_ALIGN_SZ;
32 #ifdef PLATFORM_LINUX
33 SIZE_PTR tmpaddr = 0;
34 SIZE_PTR alignment = 0;
35 #endif /* PLATFORM_LINUX */
36
37
38 size += alignsz;
39 skb = rtw_skb_alloc(size);
40 if (!skb) {
41 RTW_INFO("%s: <WARN> alloc_skb fail! size=%d\n", __FUNCTION__, size);
42 return NULL;
43 }
44
45 #ifdef PLATFORM_LINUX
46 skb->dev = recvbuf->adapter->pnetdev;
47
48 tmpaddr = (SIZE_PTR)skb->data;
49 alignment = tmpaddr & (alignsz - 1);
50 skb_reserve(skb, alignsz - alignment);
51 #endif /* PLATFORM_LINUX */
52
53 recvbuf->pskb = skb;
54
55 return skb;
56 }
57
58 /*
59 * Description:
60 * Allocate skb for recv_buf, the size is MAX_RECVBUF_SZ_8821C (24KB)
61 *
62 * Parameters:
63 * recvbuf pointer of struct recv_buf
64 * size skb size, only valid when NOT define CONFIG_SDIO_RX_COPY.
65 * If CONFIG_SDIO_RX_COPY, size always be MAX_RECVBUF_SZ_8821C.
66 *
67 * Return:
68 * Pointer of _pkt, otherwise NULL.
69 */
70 _pkt *rtl8821cs_alloc_recvbuf_skb(struct recv_buf *recvbuf, u32 size)
71 {
72 _pkt *skb;
73
74
75 skb = recvbuf->pskb;
76 #ifdef CONFIG_SDIO_RX_COPY
77 if (skb) {
78 skb_reset_tail_pointer(skb);
79 skb->len = 0;
80 return skb;
81 }
82
83 RTW_INFO("%s: <WARN> skb not exist in recv_buf!\n", __FUNCTION__);
84 size = MAX_RECVBUF_SZ_8821C;
85 #else /* !CONFIG_SDIO_RX_COPY */
86 if (skb) {
87 RTW_INFO("%s: <WARN> skb already exist in recv_buf!\n", __FUNCTION__);
88 rtl8821cs_free_recvbuf_skb(recvbuf);
89 }
90 #endif /* !CONFIG_SDIO_RX_COPY */
91
92 skb = alloc_recvbuf_skb(recvbuf, size);
93 if (!skb)
94 return NULL;
95
96 return skb;
97 }
98
99 static void free_recvbuf_skb(struct recv_buf *recvbuf)
100 {
101 _pkt *skb;
102
103
104 skb = recvbuf->pskb;
105 if (!skb)
106 return;
107 recvbuf->pskb = NULL;
108 rtw_skb_free(skb);
109 }
110
111 void rtl8821cs_free_recvbuf_skb(struct recv_buf *recvbuf)
112 {
113 #ifndef CONFIG_SDIO_RX_COPY
114 free_recvbuf_skb(recvbuf);
115 #endif /* !CONFIG_SDIO_RX_COPY */
116 }
117
118 /*
119 * Return:
120 * _SUCCESS Allocate resource OK.
121 * _FAIL Fail to allocate resource.
122 */
123 static inline s32 os_recvbuf_resource_alloc(PADAPTER adapter, struct recv_buf *recvbuf)
124 {
125 s32 ret = _SUCCESS;
126
127 #ifdef CONFIG_SDIO_RX_COPY
128 alloc_recvbuf_skb(recvbuf, MAX_RECVBUF_SZ_8821C);
129 #endif /* CONFIG_SDIO_RX_COPY */
130
131 return ret;
132 }
133
134 static inline void os_recvbuf_resource_free(PADAPTER adapter, struct recv_buf *recvbuf)
135 {
136 #ifdef CONFIG_SDIO_RX_COPY
137 free_recvbuf_skb(recvbuf);
138 #endif /* CONFIG_SDIO_RX_COPY */
139 }
140
141 static union recv_frame *copy_recvframe(union recv_frame *recvframe, PADAPTER adapter)
142 {
143 PHAL_DATA_TYPE pHalData;
144 struct recv_priv *precvpriv;
145 _queue *pfree_recv_queue;
146 struct rx_pkt_attrib *attrib = NULL;
147 union recv_frame *copyframe = NULL;
148 _pkt *copypkt = NULL;
149
150
151 pHalData = GET_HAL_DATA(adapter);
152 precvpriv = &adapter->recvpriv;
153 pfree_recv_queue = &precvpriv->free_recv_queue;
154 attrib = &recvframe->u.hdr.attrib;
155
156 copyframe = rtw_alloc_recvframe(pfree_recv_queue);
157 if (!copyframe) {
158 RTW_INFO(FUNC_ADPT_FMT ": Alloc recvframe FAIL!\n",
159 FUNC_ADPT_ARG(adapter));
160 return NULL;
161 }
162 copyframe->u.hdr.adapter = adapter;
163 _rtw_memcpy(©frame->u.hdr.attrib, attrib, sizeof(struct rx_pkt_attrib));
164 #if 0
165 /*
166 * driver need to set skb len for skb_copy().
167 * If skb->len is zero, skb_copy() will not copy data from original skb.
168 */
169 skb_put(recvframe->u.hdr.pkt, attrib->pkt_len);
170 #else
171 RTW_INFO(FUNC_ADPT_FMT ": skb len=%d!\n",
172 FUNC_ADPT_ARG(adapter), recvframe->u.hdr.pkt->len);
173 #endif
174
175 copypkt = rtw_skb_copy(recvframe->u.hdr.pkt);
176 if (!copypkt) {
177 if ((attrib->mfrag == 1) && (attrib->frag_num == 0)) {
178 RTW_INFO(FUNC_ADPT_FMT ": <ERR> rtw_skb_copy fail for first fragment!\n",
179 FUNC_ADPT_ARG(adapter));
180 rtw_free_recvframe(recvframe, &precvpriv->free_recv_queue);
181 return NULL;
182 }
183
184 copypkt = rtw_skb_clone(recvframe->u.hdr.pkt);
185 if (!copypkt) {
186 RTW_INFO(FUNC_ADPT_FMT ": <ERR> rtw_skb_clone fail, drop frame!\n",
187 FUNC_ADPT_ARG(adapter));
188 rtw_free_recvframe(recvframe, &precvpriv->free_recv_queue);
189 return NULL;
190 }
191 }
192 copypkt->dev = adapter->pnetdev;
193
194 copyframe->u.hdr.pkt = copypkt;
195 copyframe->u.hdr.len = copypkt->len;
196 copyframe->u.hdr.rx_head = copypkt->head;
197 copyframe->u.hdr.rx_data = copypkt->data;
198 copyframe->u.hdr.rx_tail = skb_tail_pointer(copypkt);
199 copyframe->u.hdr.rx_end = skb_end_pointer(copypkt);
200
201 return copyframe;
202 }
203
204 /*
205 * Return:
206 * _SUCCESS OK to send packet
207 * _FAIL FAIL to send packet
208 */
209 static s32 recv_entry(union recv_frame *recvframe, u8 *phy_status)
210 {
211 s32 ret = _SUCCESS;
212 PADAPTER adapter;
213 struct rx_pkt_attrib *attrib = NULL;
214 #ifdef CONFIG_CONCURRENT_MODE
215 struct dvobj_priv *d;
216 u8 *addr1, *macaddr;
217 u8 mcast, i;
218 union recv_frame *copyframe = NULL;
219 #endif /* CONFIG_CONCURRENT_MODE */
220
221
222 attrib = &recvframe->u.hdr.attrib;
223
224 #ifdef CONFIG_CONCURRENT_MODE
225 d = adapter_to_dvobj(recvframe->u.hdr.adapter);
226 addr1 = GetAddr1Ptr(recvframe->u.hdr.rx_data);
227 mcast = IS_MCAST(addr1);
228 if (_TRUE == mcast) {
229 /* BC/MC packets */
230 for (i = 1; i < d->iface_nums; i++) {
231 adapter = d->adapters[i];
232
233 if (rtw_if_up(adapter) == _FALSE)
234 continue;
235
236 copyframe = copy_recvframe(recvframe, adapter);
237 if (!copyframe)
238 break;
239
240 if (attrib->physt)
241 rx_query_phy_status(copyframe, phy_status);
242
243 ret = rtw_recv_entry(copyframe);
244 }
245 } else {
246 /* unicast packets */
247 for (i = 0; i < d->iface_nums; i++) {
248 adapter = d->adapters[i];
249
250 if (rtw_if_up(adapter) == _FALSE)
251 continue;
252
253 macaddr = adapter_mac_addr(adapter);
254 if (_rtw_memcmp(addr1, macaddr, ETH_ALEN) == _FALSE)
255 continue;
256
257 /* change to target interface */
258 recvframe->u.hdr.adapter = adapter;
259 recvframe->u.hdr.pkt->dev = adapter->pnetdev;
260 break;
261 }
262 }
263 #endif /* CONFIG_CONCURRENT_MODE */
264
265 if (attrib->physt)
266 rx_query_phy_status(recvframe, phy_status);
267
268 ret = rtw_recv_entry(recvframe);
269
270 return ret;
271 }
272
273 /*
274 * Return:
275 * _TRUE Finish preparing recv_frame
276 * _FALSE Something fail to prepare recv_frame
277 */
278 static _pkt *prepare_recvframe_pkt(struct recv_buf *recvbuf, union recv_frame *recvframe)
279 {
280 u32 desc_size;
281 _pkt *pkt = NULL;
282 struct rx_pkt_attrib *attrib;
283 u32 skb_len;
284 u8 *data;
285 #ifdef CONFIG_SDIO_RX_COPY
286 u32 shift_sz, alloc_sz;
287 #endif /* CONFIG_SDIO_RX_COPY */
288
289 rtw_halmac_get_rx_desc_size(adapter_to_dvobj(recvbuf->adapter), &desc_size);
290
291 pkt = recvframe->u.hdr.pkt;
292 if (pkt) {
293 RTW_INFO("%s: <WARN> recvframe pkt already exist!\n", __FUNCTION__);
294 return pkt;
295 }
296
297 attrib = &recvframe->u.hdr.attrib;
298 skb_len = attrib->pkt_len;
299 if (rtl8821c_rx_fcs_appended(recvbuf->adapter))
300 skb_len -= IEEE80211_FCS_LEN;
301 data = recvbuf->pdata + desc_size + attrib->drvinfo_sz;
302 #if 0
303 data += attrib->shift_sz;
304 #endif
305
306 #ifdef CONFIG_SDIO_RX_COPY
307 /* For 8 bytes IP header alignment. */
308 if (attrib->qos)
309 /* Qos data, wireless lan header length is 26 */
310 shift_sz = 6;
311 else
312 shift_sz = 0;
313
314 /*
315 * For first fragment packet, driver need allocate
316 * (1536 + drvinfo_sz + RXDESC_SIZE) to defrag packet.
317 * In 8821C, drvinfo_sz = 32, RXDESC_SIZE = 24, 1536 + 32 + 24 = 1592.
318 * And need 8 is for skb->data 8 bytes alignment.
319 * Round (1536 + 24 + 32 + shift_sz + 8) to 128 bytes alignment,
320 * and finally get 1664.
321 */
322 if ((attrib->mfrag == 1) && (attrib->frag_num == 0)) {
323 if (skb_len <= 1650)
324 alloc_sz = 1664;
325 else
326 alloc_sz = skb_len + 14;
327 } else {
328 alloc_sz = skb_len;
329 /*
330 * 6 is for IP header 8 bytes alignment in QoS packet case.
331 * 8 is for skb->data 4 bytes alignment.
332 */
333 alloc_sz += 14;
334 }
335
336 pkt = rtw_skb_alloc(alloc_sz);
337 if (pkt) {
338 pkt->dev = recvframe->u.hdr.adapter->pnetdev;
339 /* force pkt->data at 8-byte alignment address */
340 skb_reserve(pkt, 8 - ((SIZE_PTR)pkt->data & 7));
341 /* force ip_hdr at 8-byte alignment address according to shift_sz. */
342 skb_reserve(pkt, shift_sz);
343 _rtw_memcpy(skb_put(pkt, skb_len), data, skb_len);
344 } else if ((attrib->mfrag == 1) && (attrib->frag_num == 0)) {
345 RTW_INFO("%s: <ERR> alloc_skb fail for first fragement\n", __FUNCTION__);
346 return NULL;
347 }
348 #endif /* CONFIG_SDIO_RX_COPY */
349
350 if (!pkt) {
351 pkt = rtw_skb_clone(recvbuf->pskb);
352 if (!pkt) {
353 RTW_INFO("%s: <ERR> rtw_skb_clone fail\n", __FUNCTION__);
354 return NULL;
355 }
356 pkt->data = data;
357 skb_set_tail_pointer(pkt, skb_len);
358 pkt->len = skb_len;
359 }
360
361 recvframe->u.hdr.pkt = pkt;
362 recvframe->u.hdr.len = pkt->len;
363 recvframe->u.hdr.rx_head = pkt->head;
364 recvframe->u.hdr.rx_data = pkt->data;
365 recvframe->u.hdr.rx_tail = skb_tail_pointer(pkt);
366 recvframe->u.hdr.rx_end = skb_end_pointer(pkt);
367
368 return pkt;
369 }
370
371 /*
372 * process Normal Rx packets
373 * Return:
374 * _TRUE Finish processing recv_buf
375 * _FALSE Something fail to process recv_buf
376 */
377 static u8 recvbuf_handler(struct recv_buf *recvbuf)
378 {
379 PADAPTER p;
380 struct recv_priv *recvpriv;
381 union recv_frame *recvframe;
382 struct rx_pkt_attrib *attrib;
383 _pkt *pkt;
384 u32 desc_size;
385 u32 rx_report_sz, pkt_offset;
386 u8 *ptr;
387 u8 ret = _TRUE;
388
389
390 p = recvbuf->adapter;
391 recvpriv = &p->recvpriv;
392 ptr = recvbuf->pdata;
393 rtw_halmac_get_rx_desc_size(adapter_to_dvobj(p), &desc_size);
394
395 while (ptr < recvbuf->ptail) {
396 recvframe = rtw_alloc_recvframe(&recvpriv->free_recv_queue);
397 if (!recvframe) {
398 RTW_INFO("%s: <WARN> no enough recv frame!\n", __FUNCTION__);
399 ret = _FALSE;
400 break;
401 }
402
403 /* rx desc parsing */
404 attrib = &recvframe->u.hdr.attrib;
405 rtl8821c_rxdesc2attribute(attrib, ptr);
406
407 rx_report_sz = desc_size + attrib->drvinfo_sz;
408 pkt_offset = rx_report_sz + attrib->shift_sz + attrib->pkt_len;
409
410 if ((ptr + pkt_offset) > recvbuf->ptail) {
411 RTW_INFO("%s: <WARN> next pkt len(%p,%d) exceed ptail(%p)!\n",
412 __FUNCTION__, ptr, pkt_offset, recvbuf->ptail);
413 rtw_free_recvframe(recvframe, &recvpriv->free_recv_queue);
414 break;
415 }
416
417 /* fix Hardware RX data error, drop whole recv_buffer */
418 if (!rtw_hal_rcr_check(p, BIT_ACRC32_8821C)
419 && attrib->crc_err) {
420 RTW_INFO("%s: <WARN> Received unexpected CRC error packet!!\n", __FUNCTION__);
421 rtw_free_recvframe(recvframe, &recvpriv->free_recv_queue);
422 break;
423 }
424
425 if ((attrib->crc_err) || (attrib->icv_err)) {
426 #ifdef CONFIG_MP_INCLUDED
427 if (p->registrypriv.mp_mode == 1) {
428 if (check_fwstate(&p->mlmepriv, WIFI_MP_STATE) == _TRUE) {
429 if (attrib->crc_err == 1)
430 p->mppriv.rx_crcerrpktcount++;
431 }
432 } else
433 #endif /* CONFIG_MP_INCLUDED */
434 {
435 RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n",
436 __FUNCTION__, attrib->crc_err, attrib->icv_err);
437 }
438 rtw_free_recvframe(recvframe, &recvpriv->free_recv_queue);
439 } else {
440 pkt = prepare_recvframe_pkt(recvbuf, recvframe);
441 if (!pkt) {
442 rtw_free_recvframe(recvframe, &recvpriv->free_recv_queue);
443 ret = _FALSE;
444 break;
445 }
446
447 /* move to start of PHY_STATUS */
448 ptr += desc_size;
449 if (rtl8821c_rx_ba_ssn_appended(p))
450 ptr += RTW_HALMAC_BA_SSN_RPT_SIZE;
451
452 recv_entry(recvframe, ptr);
453 }
454
455 pkt_offset = _RND8(pkt_offset);
456 recvbuf->pdata += pkt_offset;
457 ptr = recvbuf->pdata;
458 }
459
460 return ret;
461 }
462
463 static void rtl8821c_recv_tasklet(unsigned long priv)
464 {
465 PADAPTER adapter;
466 struct recv_priv *recvpriv;
467 struct recv_buf *recvbuf;
468 u8 ret = _TRUE;
469
470
471 adapter = (PADAPTER)priv;
472 recvpriv = &adapter->recvpriv;
473
474 do {
475 recvbuf = rtw_dequeue_recvbuf(&recvpriv->recv_buf_pending_queue);
476 if (NULL == recvbuf)
477 break;
478
479
480 if (GET_RX_DESC_C2H_8821C(recvbuf->pdata)) {
481 if (GET_RX_DESC_DRV_INFO_SIZE_8821C(recvbuf->pdata)) {
482 RTW_INFO("%s [WARN] DRV_INFO_SIZE != 0\n", __func__);
483 rtw_warn_on(1);
484 }
485
486 c2h_pre_handler_rtl8821c(adapter, recvbuf->pdata, recvbuf->len);
487 } else
488 ret = recvbuf_handler(recvbuf);
489
490 if (_FALSE == ret) {
491 rtw_enqueue_recvbuf_to_head(recvbuf, &recvpriv->recv_buf_pending_queue);
492 rtw_msleep_os(5);
493 start_rx_handle(adapter);
494 break;
495 }
496
497 /* free recv_buf */
498 rtl8821cs_free_recvbuf_skb(recvbuf);
499 rtw_enqueue_recvbuf(recvbuf, &recvpriv->free_recv_buf_queue);
500 } while (1);
501 }
502 #endif
503
504 #ifdef CONFIG_SDIO_RX_COPY
rtl8821cs_recv_hdl(_adapter * padapter)505 s32 rtl8821cs_recv_hdl(_adapter *padapter)
506 {
507 PHAL_DATA_TYPE pHalData;
508 struct recv_priv *precvpriv;
509 struct recv_buf *precvbuf;
510 union recv_frame *precvframe;
511 struct recv_frame_hdr *phdr;
512 struct rx_pkt_attrib *pattrib;
513 u8 *ptr;
514 u32 desc_size;
515 u32 pkt_offset;
516 s32 transfer_len;
517 u8 *pphy_status = NULL;
518 u8 rx_report_sz = 0;
519
520 pHalData = GET_HAL_DATA(padapter);
521 precvpriv = &padapter->recvpriv;
522
523 rtw_halmac_get_rx_desc_size(adapter_to_dvobj(padapter), &desc_size);
524
525 do {
526 if (RTW_CANNOT_RUN(padapter)) {
527 RTW_INFO("%s => bDriverStopped or bSurpriseRemoved\n", __func__);
528 break;
529 }
530
531 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
532 if (NULL == precvbuf)
533 break;
534
535 transfer_len = (s32)precvbuf->len;
536 ptr = precvbuf->pdata;
537
538 do {
539 precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
540 if (precvframe == NULL) {
541 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
542 return RTW_RFRAME_UNAVAIL;
543 }
544
545 /*rx desc parsing*/
546 pattrib = &precvframe->u.hdr.attrib;
547 rtl8821c_rxdesc2attribute(pattrib, ptr);
548
549 /* fix Hardware RX data error, drop whole recv_buffer*/
550 if (!rtw_hal_rcr_check(padapter, BIT_ACRC32_8821C) && pattrib->crc_err) {
551
552 if (padapter->registrypriv.mp_mode == 0)
553 RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __func__, __LINE__);
554
555 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
556 break;
557 }
558
559 /*if (rtl8821c_rx_ba_ssn_appended(p))*/
560 if (rtw_hal_rcr_check(padapter, BIT_APP_BASSN_8821C))
561 rx_report_sz = desc_size + RTW_HALMAC_BA_SSN_RPT_SIZE + pattrib->drvinfo_sz;
562 else
563 rx_report_sz = desc_size + pattrib->drvinfo_sz;
564
565 pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
566
567 if ((pattrib->pkt_len == 0) || (pkt_offset > transfer_len)) {
568 RTW_INFO("%s()-%d: RX Warning!, pkt_len==0 or pkt_offset(%d)> transfoer_len(%d)\n", __func__, __LINE__, pkt_offset, transfer_len);
569 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
570 break;
571 }
572
573 if ((pattrib->crc_err) || (pattrib->icv_err)) {
574 #ifdef CONFIG_MP_INCLUDED
575 if (padapter->registrypriv.mp_mode == 1) {
576 if (check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE)) { /*&&(padapter->mppriv.check_mp_pkt == 0))*/
577 if (pattrib->crc_err == 1)
578 padapter->mppriv.rx_crcerrpktcount++;
579 }
580 }
581 #endif
582
583 RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
584 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
585 } else {
586
587 if (pattrib->pkt_rpt_type == NORMAL_RX) { /*Normal rx packet*/
588
589 #ifdef CONFIG_RX_PACKET_APPEND_FCS
590 if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE)
591 if ((pattrib->pkt_rpt_type == NORMAL_RX) && rtw_hal_rcr_check(padapter, BIT_APP_FCS_8821C))
592 pattrib->pkt_len -= IEEE80211_FCS_LEN;
593 #endif
594
595 if (rtw_os_alloc_recvframe(padapter, precvframe,
596 (ptr + rx_report_sz + pattrib->shift_sz), precvbuf->pskb) == _FAIL) {
597 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
598 break;
599 }
600
601 recvframe_put(precvframe, pattrib->pkt_len);
602 /*recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);*/
603
604
605 /* update drv info*/
606 #if 0
607 if (rtw_hal_rcr_check(padapter, BIT_APP_BASSN_8821C)) {
608 /*rtl8821c_update_bassn(padapter, (ptr + RXDESC_SIZE));*/
609 }
610 #endif
611
612 pre_recv_entry(precvframe, pattrib->physt ? (ptr + rx_report_sz - pattrib->drvinfo_sz) : NULL);
613
614 } else { /* C2H_PACKET */
615
616 c2h_pre_handler_rtl8821c(padapter, ptr, transfer_len);
617 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
618
619 }
620 }
621
622 /* Page size of receive package is 128 bytes alignment =>DMA AGG*/
623
624 pkt_offset = _RND8(pkt_offset);
625 transfer_len -= pkt_offset;
626 ptr += pkt_offset;
627 precvframe = NULL;
628
629 } while (transfer_len > 0);
630
631 precvbuf->len = 0;
632
633 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
634 } while (1);
635
636 #ifdef CONFIG_RTW_NAPI
637 #ifdef CONFIG_RTW_NAPI_V2
638 if (padapter->registrypriv.en_napi) {
639 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
640 struct _ADAPTER *iface;
641 u8 i;
642
643 for (i = 0; i < dvobj->iface_nums; i++) {
644 iface = dvobj->padapters[i];
645 precvpriv = &iface->recvpriv;
646 if (rtw_if_up(iface) == _TRUE
647 && skb_queue_len(&precvpriv->rx_napi_skb_queue))
648 napi_schedule(&iface->napi);
649 }
650 }
651 #endif /* CONFIG_RTW_NAPI_V2 */
652 #endif /* CONFIG_RTW_NAPI */
653
654 return _SUCCESS;
655
656 }
657
rtl8821c_recv_tasklet(unsigned long priv)658 static void rtl8821c_recv_tasklet(unsigned long priv)
659 {
660 _adapter *adapter = (_adapter *)priv;
661 s32 ret;
662
663 ret = rtl8821cs_recv_hdl(adapter);
664 if (ret == RTW_RFRAME_UNAVAIL
665 || ret == RTW_RFRAME_PKT_UNAVAIL
666 ) {
667 /* schedule again and hope recvframe/packet is available next time. */
668 #ifdef PLATFORM_LINUX
669 tasklet_schedule(&adapter->recvpriv.recv_tasklet);
670 #endif
671 }
672 }
673
674 #else
675
rtl8821c_recv_tasklet(unsigned long priv)676 static void rtl8821c_recv_tasklet(unsigned long priv)
677 {
678 PADAPTER padapter;
679 PHAL_DATA_TYPE pHalData;
680 struct recv_priv *precvpriv;
681 struct recv_buf *precvbuf;
682 union recv_frame *precvframe;
683 struct recv_frame_hdr *phdr;
684 struct rx_pkt_attrib *pattrib;
685 u8 *ptr;
686 _pkt *ppkt;
687 u32 desc_size;
688 u32 pkt_offset;
689
690 padapter = (PADAPTER)priv;
691 pHalData = GET_HAL_DATA(padapter);
692 precvpriv = &padapter->recvpriv;
693 rtw_halmac_get_rx_desc_size(adapter_to_dvobj(padapter), &desc_size);
694
695 do {
696 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
697 if (NULL == precvbuf)
698 break;
699
700 ptr = precvbuf->pdata;
701
702 while (ptr < precvbuf->ptail) {
703 precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
704 if (precvframe == NULL) {
705 RTW_ERR("%s: no enough recv frame!\n", __FUNCTION__);
706 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
707
708 /* The case of can't allocate recvframe should be temporary,
709 schedule again and hope recvframe is available next time.*/
710 tasklet_schedule(&precvpriv->recv_tasklet);
711
712 return;
713 }
714
715 phdr = &precvframe->u.hdr;
716 pattrib = &phdr->attrib;
717
718 /*rx desc parsing*/
719 rtl8821c_rxdesc2attribute(pattrib, ptr);
720
721 /* fix Hardware RX data error, drop whole recv_buffer*/
722 if (!rtw_hal_rcr_check(padapter, BIT_ACRC32_8821C) && pattrib->crc_err) {
723 /*#if !(MP_DRIVER==1)*/
724 if (padapter->registrypriv.mp_mode == 0)
725 RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
726 /*#endif*/
727 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
728 break;
729 }
730
731 pkt_offset = desc_size + pattrib->drvinfo_sz + pattrib->pkt_len;
732
733 if ((ptr + pkt_offset) > precvbuf->ptail) {
734 RTW_INFO("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
735 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
736 break;
737 }
738
739 if ((pattrib->crc_err) || (pattrib->icv_err)) {
740 #ifdef CONFIG_MP_INCLUDED
741 if (padapter->registrypriv.mp_mode == 1) {
742 if (check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE)) { /*&&(padapter->mppriv.check_mp_pkt == 0))*/
743 if (pattrib->crc_err == 1)
744 padapter->mppriv.rx_crcerrpktcount++;
745 }
746 }
747 #endif
748
749 RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
750 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
751 } else {
752 ppkt = rtw_skb_clone(precvbuf->pskb);
753 if (ppkt == NULL) {
754 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
755 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
756
757 /* The case of can't allocate skb is serious and may never be recovered,
758 once bDriverStopped is enable, this task should be stopped.*/
759 if (!rtw_is_drv_stopped(padapter))
760 tasklet_schedule(&precvpriv->recv_tasklet);
761
762 return;
763 }
764
765 phdr->pkt = ppkt;
766 phdr->len = 0;
767 phdr->rx_head = precvbuf->phead;
768 phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
769 phdr->rx_end = precvbuf->pend;
770
771 recvframe_put(precvframe, pkt_offset);
772 recvframe_pull(precvframe, desc_size + pattrib->drvinfo_sz);
773 skb_pull(ppkt, desc_size + pattrib->drvinfo_sz);
774
775 #ifdef CONFIG_RX_PACKET_APPEND_FCS
776 if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE) {
777 if ((pattrib->pkt_rpt_type == NORMAL_RX) && rtw_hal_rcr_check(padapter, BIT_APP_FCS_8821C)) {
778 recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
779 pattrib->pkt_len -= IEEE80211_FCS_LEN;
780 ppkt->len = pattrib->pkt_len;
781 }
782 }
783 #endif
784
785 /* move to drv info position*/
786 ptr += desc_size;
787
788 /* update drv info*/
789 if (rtw_hal_rcr_check(padapter, BIT_APP_BASSN_8821C)) {
790 /*rtl8821cs_update_bassn(padapter, pdrvinfo);*/
791 ptr += RTW_HALMAC_BA_SSN_RPT_SIZE;
792 }
793
794 if (pattrib->pkt_rpt_type == NORMAL_RX) /*Normal rx packet*/
795 pre_recv_entry(precvframe, pattrib->physt ? ptr : NULL);
796 else { /* C2H_PACKET*/
797 c2h_pre_handler_rtl8821c(padapter, ptr, transfer_len);
798 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
799 }
800 }
801
802 /* Page size of receive package is 128 bytes alignment =>DMA AGG*/
803
804 pkt_offset = _RND8(pkt_offset);
805 precvbuf->pdata += pkt_offset;
806 ptr = precvbuf->pdata;
807
808 }
809
810 rtw_skb_free(precvbuf->pskb);
811 precvbuf->pskb = NULL;
812 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
813
814 } while (1);
815
816 }
817 #endif
818
819 /*
820 * Initialize recv private variable for hardware dependent
821 * 1. recv buf
822 * 2. recv tasklet
823 */
rtl8821cs_init_recv_priv(PADAPTER adapter)824 s32 rtl8821cs_init_recv_priv(PADAPTER adapter)
825 {
826 struct registry_priv *regsty = adapter_to_regsty(adapter);
827 s32 res;
828 u32 i, n;
829 struct recv_priv *precvpriv;
830 struct recv_buf *precvbuf;
831
832
833 res = _SUCCESS;
834 precvpriv = &adapter->recvpriv;
835
836 /* 1. init recv buffer */
837 _rtw_init_queue(&precvpriv->free_recv_buf_queue);
838 _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
839
840 n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
841 precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
842 if (precvpriv->pallocated_recv_buf == NULL) {
843 res = _FAIL;
844 goto exit;
845 }
846
847 precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
848
849 /* init each recv buffer */
850 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
851 for (i = 0; i < regsty->recvbuf_nr; i++) {
852 res = sdio_initrecvbuf(precvbuf, adapter);
853 if (res == _FAIL)
854 break;
855
856 res = rtw_os_recvbuf_resource_alloc(adapter, precvbuf, MAX_RECVBUF_SZ);
857 if (res == _FAIL) {
858 sdio_freerecvbuf(precvbuf);
859 break;
860 }
861
862 #if 0
863 res = os_recvbuf_resource_alloc(adapter, precvbuf);
864 if (res == _FAIL) {
865 sdio_freerecvbuf(precvbuf);
866 break;
867 }
868 #endif
869 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
870
871 precvbuf++;
872 }
873 precvpriv->free_recv_buf_queue_cnt = i;
874
875 if (res == _FAIL)
876 goto initbuferror;
877
878 /* 2. init tasklet */
879 #ifdef PLATFORM_LINUX
880 tasklet_init(&precvpriv->recv_tasklet,
881 rtl8821c_recv_tasklet,
882 (unsigned long)adapter);
883 #endif
884
885 goto exit;
886
887 initbuferror:
888 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
889 if (precvbuf) {
890 n = precvpriv->free_recv_buf_queue_cnt;
891 precvpriv->free_recv_buf_queue_cnt = 0;
892 for (i = 0; i < n ; i++) {
893 rtw_list_delete(&precvbuf->list);
894 rtw_os_recvbuf_resource_free(adapter, precvbuf);
895 sdio_freerecvbuf(precvbuf);
896 precvbuf++;
897 }
898 precvpriv->precv_buf = NULL;
899 }
900
901 if (precvpriv->pallocated_recv_buf) {
902 n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
903 rtw_mfree(precvpriv->pallocated_recv_buf, n);
904 precvpriv->pallocated_recv_buf = NULL;
905 }
906
907 exit:
908 return res;
909 }
910
911 /*
912 * Free recv private variable of hardware dependent
913 * 1. recv buf
914 * 2. recv tasklet
915 */
rtl8821cs_free_recv_priv(PADAPTER adapter)916 void rtl8821cs_free_recv_priv(PADAPTER adapter)
917 {
918 struct registry_priv *regsty = &adapter->registrypriv;
919 u32 i, n;
920 struct recv_priv *precvpriv;
921 struct recv_buf *precvbuf;
922
923
924 precvpriv = &adapter->recvpriv;
925
926 /* 1. kill tasklet */
927 #ifdef PLATFORM_LINUX
928 tasklet_kill(&adapter->recvpriv.recv_tasklet);
929 #endif
930
931 /* 2. free all recv buffers */
932 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
933 if (precvbuf) {
934 n = regsty->recvbuf_nr;
935 precvpriv->free_recv_buf_queue_cnt = 0;
936 for (i = 0; i < n ; i++) {
937 rtw_list_delete(&precvbuf->list);
938 rtw_os_recvbuf_resource_free(adapter, precvbuf);
939 sdio_freerecvbuf(precvbuf);
940 precvbuf++;
941 }
942 precvpriv->precv_buf = NULL;
943 }
944
945 if (precvpriv->pallocated_recv_buf) {
946 n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
947 rtw_mfree(precvpriv->pallocated_recv_buf, n);
948 precvpriv->pallocated_recv_buf = NULL;
949 }
950 }
951
rtl8821cs_rxhandler(PADAPTER adapter,struct recv_buf * recvbuf)952 void rtl8821cs_rxhandler(PADAPTER adapter, struct recv_buf *recvbuf)
953 {
954 struct recv_priv *recvpriv = &adapter->recvpriv;
955 _queue *pending_queue = &recvpriv->recv_buf_pending_queue;
956
957
958 /*enqueue recvbuf*/
959 rtw_enqueue_recvbuf(recvbuf, pending_queue);
960
961 /*schedule tasklet*/
962 #ifdef CONFIG_RECV_THREAD_MODE
963 _rtw_up_sema(&recvpriv->recv_sema);
964 #else
965 #ifdef PLATFORM_LINUX
966 tasklet_schedule(&recvpriv->recv_tasklet);
967 #endif
968 #endif
969 }
970