xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8821cs/hal/rtl8821c/sdio/rtl8821cs_recv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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(&copyframe->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