xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/sdio/rtl8703bs_recv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 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 _RTL8703BS_RECV_C_
16 
17 #include <rtl8703b_hal.h>
18 
19 #ifdef CONFIG_SDIO_RX_COPY
rtl8703bs_recv_hdl(_adapter * padapter)20 s32 rtl8703bs_recv_hdl(_adapter *padapter)
21 {
22 	PHAL_DATA_TYPE		pHalData;
23 	struct recv_priv		*precvpriv;
24 	struct recv_buf	*precvbuf;
25 	union recv_frame		*precvframe;
26 	struct recv_frame_hdr	*phdr;
27 	struct rx_pkt_attrib	*pattrib;
28 	u8	*ptr;
29 	u32	pkt_len, pkt_offset;
30 	u8	rx_report_sz = 0;
31 
32 	pHalData = GET_HAL_DATA(padapter);
33 	precvpriv = &padapter->recvpriv;
34 
35 	do {
36 		precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
37 		if (NULL == precvbuf)
38 			break;
39 
40 		ptr = precvbuf->pdata;
41 
42 		while (ptr < precvbuf->ptail) {
43 			precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
44 			if (precvframe == NULL) {
45 				RTW_INFO("%s: no enough recv frame!\n", __FUNCTION__);
46 				rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
47 
48 				return RTW_RFRAME_UNAVAIL;
49 			}
50 
51 			/* rx desc parsing */
52 			rtl8703b_query_rx_desc_status(precvframe, ptr);
53 
54 			pattrib = &precvframe->u.hdr.attrib;
55 
56 			/* fix Hardware RX data error, drop whole recv_buffer */
57 			if (!rtw_hal_rcr_check(padapter, RCR_ACRC32) && pattrib->crc_err) {
58 #if !(MP_DRIVER == 1)
59 				RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
60 #endif
61 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
62 				break;
63 			}
64 
65 			rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
66 			pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
67 
68 			if ((ptr + pkt_offset) > precvbuf->ptail) {
69 				RTW_INFO("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
70 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
71 				break;
72 			}
73 
74 			if ((pattrib->crc_err) || (pattrib->icv_err)) {
75 #ifdef CONFIG_MP_INCLUDED
76 				if (padapter->registrypriv.mp_mode == 1) {
77 					if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE)) { /* &&(padapter->mppriv.check_mp_pkt == 0)) */
78 						if (pattrib->crc_err == 1)
79 							padapter->mppriv.rx_crcerrpktcount++;
80 					}
81 				} else
82 #endif
83 				{
84 					RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
85 				}
86 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
87 			} else {
88 #ifdef CONFIG_RX_PACKET_APPEND_FCS
89 				if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE)
90 					if ((pattrib->pkt_rpt_type == NORMAL_RX) && rtw_hal_rcr_check(padapter, RCR_APPFCS))
91 						pattrib->pkt_len -= IEEE80211_FCS_LEN;
92 #endif
93 
94 				if (rtw_os_alloc_recvframe(padapter, precvframe,
95 					(ptr + rx_report_sz + pattrib->shift_sz), precvbuf->pskb) == _FAIL) {
96 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
97 					break;
98 				}
99 				recvframe_put(precvframe, pattrib->pkt_len);
100 				/* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */
101 
102 				/* move to drv info position */
103 				ptr += RXDESC_SIZE;
104 
105 				/* update drv info */
106 				if (rtw_hal_rcr_check(padapter, RCR_APP_BA_SSN)) {
107 					/* rtl8703s_update_bassn(padapter, pdrvinfo); */
108 					ptr += 4;
109 				}
110 
111 				if (pattrib->pkt_rpt_type == NORMAL_RX) {
112 					/* skip the rx packet with abnormal length */
113 					if (pattrib->pkt_len < 14 || pattrib->pkt_len > 8192) {
114 						RTW_INFO("skip abnormal rx packet(%d)\n", pattrib->pkt_len);
115 						rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
116 						break;
117 					}
118 
119 					pre_recv_entry(precvframe, pattrib->physt ? ptr : NULL);
120 
121 				} else {
122 #ifdef CONFIG_FW_C2H_PKT
123 					if (pattrib->pkt_rpt_type == C2H_PACKET)
124 						rtw_hal_c2h_pkt_pre_hdl(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
125 					else {
126 						RTW_INFO("%s: [WARNNING] RX type(%d) not be handled!\n",
127 							__FUNCTION__, pattrib->pkt_rpt_type);
128 					}
129 #endif
130 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
131 				}
132 			}
133 
134 			pkt_offset = _RND8(pkt_offset);
135 			precvbuf->pdata += pkt_offset;
136 			ptr = precvbuf->pdata;
137 			precvframe = NULL;
138 		}
139 
140 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
141 	} while (1);
142 
143 #ifdef CONFIG_RTW_NAPI
144 #ifdef CONFIG_RTW_NAPI_V2
145 		if (padapter->registrypriv.en_napi) {
146 			struct dvobj_priv *d;
147 			struct _ADAPTER *a;
148 			u8 i;
149 
150 			d = adapter_to_dvobj(padapter);
151 			for (i = 0; i < d->iface_nums; i++) {
152 				a = d->padapters[i];
153 				if (rtw_if_up(a) == _TRUE)
154 					napi_schedule(&a->napi);
155 
156 			}
157 		}
158 #endif /* CONFIG_RTW_NAPI_V2 */
159 #endif /* CONFIG_RTW_NAPI */
160 
161 		return _SUCCESS;
162 	}
163 
rtl8703bs_recv_tasklet(void * priv)164 	static void rtl8703bs_recv_tasklet(void *priv)
165 	{
166 		_adapter *adapter = (_adapter *)priv;
167 		s32 ret;
168 
169 		ret = rtl8703bs_recv_hdl(adapter);
170 		if (ret == RTW_RFRAME_UNAVAIL
171 			|| ret == RTW_RFRAME_PKT_UNAVAIL
172 		) {
173 			/* schedule again and hope recvframe/packet is available next time. */
174 		#ifdef PLATFORM_LINUX
175 			tasklet_schedule(&adapter->recvpriv.recv_tasklet);
176 		#endif
177 		}
178 	}
179 #else
rtl8703bs_recv_tasklet(void * priv)180 static void rtl8703bs_recv_tasklet(void *priv)
181 {
182 	PADAPTER				padapter;
183 	PHAL_DATA_TYPE			pHalData;
184 	struct recv_priv		*precvpriv;
185 	struct recv_buf		*precvbuf;
186 	union recv_frame		*precvframe;
187 	struct recv_frame_hdr	*phdr;
188 	struct rx_pkt_attrib	*pattrib;
189 	u8		*ptr;
190 	_pkt		*ppkt;
191 	u32		pkt_offset;
192 
193 	padapter = (PADAPTER)priv;
194 	pHalData = GET_HAL_DATA(padapter);
195 	precvpriv = &padapter->recvpriv;
196 
197 	do {
198 		precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
199 		if (NULL == precvbuf)
200 			break;
201 
202 		ptr = precvbuf->pdata;
203 
204 		while (ptr < precvbuf->ptail) {
205 			precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
206 			if (precvframe == NULL) {
207 				rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
208 
209 				/* The case of can't allocte recvframe should be temporary, */
210 				/* schedule again and hope recvframe is available next time. */
211 #ifdef PLATFORM_LINUX
212 				tasklet_schedule(&precvpriv->recv_tasklet);
213 #endif
214 				return;
215 			}
216 
217 			phdr = &precvframe->u.hdr;
218 			pattrib = &phdr->attrib;
219 
220 			rtl8703b_query_rx_desc_status(precvframe, ptr);
221 
222 #if 0
223 			{
224 				int i, len = 64;
225 				u8 *pptr = ptr;
226 
227 				if ((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40)) {
228 					RTW_INFO("##############RxDESC###############\n");
229 					for (i = 0; i < 32; i = i + 16)
230 						RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr + i),
231 							*(pptr + i + 1), *(pptr + i + 2) , *(pptr + i + 3) , *(pptr + i + 4), *(pptr + i + 5), *(pptr + i + 6), *(pptr + i + 7), *(pptr + i + 8),
232 							*(pptr + i + 9), *(pptr + i + 10),
233 							*(pptr + i + 11), *(pptr + i + 12), *(pptr + i + 13), *(pptr + i + 14), *(pptr + i + 15));
234 
235 					if (pattrib->pkt_len < 100)
236 						len = pattrib->pkt_len;
237 					pptr = ptr + RXDESC_SIZE + pattrib->drvinfo_sz;
238 					RTW_INFO("##############Len=%d###############\n", pattrib->pkt_len);
239 					for (i = 0; i < len; i = i + 16)
240 						RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr + i),
241 							*(pptr + i + 1), *(pptr + i + 2) , *(pptr + i + 3) , *(pptr + i + 4), *(pptr + i + 5), *(pptr + i + 6), *(pptr + i + 7), *(pptr + i + 8),
242 							*(pptr + i + 9), *(pptr + i + 10),
243 							*(pptr + i + 11), *(pptr + i + 12), *(pptr + i + 13), *(pptr + i + 14), *(pptr + i + 15));
244 					RTW_INFO("#############################\n");
245 				}
246 			}
247 #endif
248 
249 			/* fix Hardware RX data error, drop whole recv_buffer */
250 			if (!rtw_hal_rcr_check(padapter, RCR_ACRC32) && pattrib->crc_err) {
251 				RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
252 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
253 				break;
254 			}
255 
256 			pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
257 #if 0 /* reduce check to speed up */
258 			if ((ptr + pkt_offset) > precvbuf->ptail) {
259 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
260 				break;
261 			}
262 #endif
263 
264 			if ((pattrib->crc_err) || (pattrib->icv_err)) {
265 #ifdef CONFIG_MP_INCLUDED
266 				if (padapter->registrypriv.mp_mode == 1) {
267 					if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE)) { /* &&(padapter->mppriv.check_mp_pkt == 0)) */
268 						if (pattrib->crc_err == 1)
269 							padapter->mppriv.rx_crcerrpktcount++;
270 					}
271 				} else
272 #endif
273 				{
274 					RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
275 				}
276 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
277 			} else {
278 				ppkt = rtw_skb_clone(precvbuf->pskb);
279 				if (ppkt == NULL) {
280 					RTW_INFO("%s: no enough memory to allocate SKB!\n", __FUNCTION__);
281 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
282 					rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
283 
284 					/* The case of can't allocte skb is serious and may never be recovered, */
285 					/* once bDriverStopped is enable, this task should be stopped. */
286 					if (!rtw_is_drv_stopped(padapter)) {
287 #ifdef PLATFORM_LINUX
288 						tasklet_schedule(&precvpriv->recv_tasklet);
289 #endif
290 					}
291 
292 					return;
293 				}
294 
295 				phdr->pkt = ppkt;
296 				phdr->len = 0;
297 				phdr->rx_head = precvbuf->phead;
298 				phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
299 				phdr->rx_end = precvbuf->pend;
300 				recvframe_put(precvframe, pkt_offset);
301 				recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
302 				skb_pull(ppkt, RXDESC_SIZE + pattrib->drvinfo_sz);
303 
304 #ifdef CONFIG_RX_PACKET_APPEND_FCS
305 				if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE) {
306 					if ((pattrib->pkt_rpt_type == NORMAL_RX) && rtw_hal_rcr_check(padapter, RCR_APPFCS)) {
307 						recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
308 						pattrib->pkt_len -= IEEE80211_FCS_LEN;
309 						ppkt->len = pattrib->pkt_len;
310 					}
311 				}
312 #endif
313 
314 				/* move to drv info position */
315 				ptr += RXDESC_SIZE;
316 
317 				/* update drv info */
318 				if (rtw_hal_rcr_check(padapter, RCR_APP_BA_SSN)) {
319 					/* rtl8703s_update_bassn(padapter, pdrvinfo); */
320 					ptr += 4;
321 				}
322 
323 				if (pattrib->pkt_rpt_type == NORMAL_RX)
324 					pre_recv_entry(precvframe, pattrib->physt ? ptr : NULL);
325 				else {
326 #ifdef CONFIG_FW_C2H_PKT
327 					if (pattrib->pkt_rpt_type == C2H_PACKET)
328 						rtw_hal_c2h_pkt_pre_hdl(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
329 					else {
330 						RTW_INFO("%s: [WARNNING] RX type(%d) not be handled!\n",
331 							__FUNCTION__, pattrib->pkt_rpt_type);
332 					}
333 #endif
334 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
335 				}
336 			}
337 
338 			pkt_offset = _RND8(pkt_offset);
339 			precvbuf->pdata += pkt_offset;
340 			ptr = precvbuf->pdata;
341 		}
342 
343 		rtw_skb_free(precvbuf->pskb);
344 		precvbuf->pskb = NULL;
345 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
346 	} while (1);
347 }
348 #endif
349 
350 /*
351  * Initialize recv private variable for hardware dependent
352  * 1. recv buf
353  * 2. recv tasklet
354  *
355  */
rtl8703bs_init_recv_priv(PADAPTER padapter)356 s32 rtl8703bs_init_recv_priv(PADAPTER padapter)
357 {
358 	struct registry_priv *regsty = adapter_to_regsty(padapter);
359 	s32			res;
360 	u32			i, n;
361 	struct recv_priv	*precvpriv;
362 	struct recv_buf		*precvbuf;
363 
364 
365 	res = _SUCCESS;
366 	precvpriv = &padapter->recvpriv;
367 
368 	/* 3 1. init recv buffer */
369 	_rtw_init_queue(&precvpriv->free_recv_buf_queue);
370 	_rtw_init_queue(&precvpriv->recv_buf_pending_queue);
371 
372 	n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
373 	precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
374 	if (precvpriv->pallocated_recv_buf == NULL) {
375 		res = _FAIL;
376 		goto exit;
377 	}
378 
379 	precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
380 
381 	/* init each recv buffer */
382 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
383 	for (i = 0; i < regsty->recvbuf_nr; i++) {
384 		res = sdio_initrecvbuf(precvbuf, padapter);
385 		if (res == _FAIL)
386 			break;
387 
388 		res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf, MAX_RECVBUF_SZ);
389 		if (res == _FAIL) {
390 			sdio_freerecvbuf(precvbuf);
391 			break;
392 		}
393 
394 		rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
395 
396 		precvbuf++;
397 	}
398 	precvpriv->free_recv_buf_queue_cnt = i;
399 
400 	if (res == _FAIL)
401 		goto initbuferror;
402 
403 	/* 3 2. init tasklet */
404 #ifdef PLATFORM_LINUX
405 	tasklet_init(&precvpriv->recv_tasklet,
406 		     (void(*)(unsigned long))rtl8703bs_recv_tasklet,
407 		     (unsigned long)padapter);
408 #endif
409 
410 	goto exit;
411 
412 initbuferror:
413 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
414 	if (precvbuf) {
415 		n = precvpriv->free_recv_buf_queue_cnt;
416 		precvpriv->free_recv_buf_queue_cnt = 0;
417 		for (i = 0; i < n ; i++) {
418 			rtw_list_delete(&precvbuf->list);
419 			rtw_os_recvbuf_resource_free(padapter, precvbuf);
420 			sdio_freerecvbuf(precvbuf);
421 			precvbuf++;
422 		}
423 		precvpriv->precv_buf = NULL;
424 	}
425 
426 	if (precvpriv->pallocated_recv_buf) {
427 		n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
428 		rtw_mfree(precvpriv->pallocated_recv_buf, n);
429 		precvpriv->pallocated_recv_buf = NULL;
430 	}
431 
432 exit:
433 	return res;
434 }
435 
436 /*
437  * Free recv private variable of hardware dependent
438  * 1. recv buf
439  * 2. recv tasklet
440  *
441  */
rtl8703bs_free_recv_priv(PADAPTER padapter)442 void rtl8703bs_free_recv_priv(PADAPTER padapter)
443 {
444 	struct registry_priv *regsty = &padapter->registrypriv;
445 	u32			i, n;
446 	struct recv_priv	*precvpriv;
447 	struct recv_buf		*precvbuf;
448 
449 
450 	precvpriv = &padapter->recvpriv;
451 
452 	/* 3 1. kill tasklet */
453 #ifdef PLATFORM_LINUX
454 	tasklet_kill(&precvpriv->recv_tasklet);
455 #endif
456 
457 	/* 3 2. free all recv buffers */
458 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
459 	if (precvbuf) {
460 		n = regsty->recvbuf_nr;
461 		precvpriv->free_recv_buf_queue_cnt = 0;
462 		for (i = 0; i < n ; i++) {
463 			rtw_list_delete(&precvbuf->list);
464 			rtw_os_recvbuf_resource_free(padapter, precvbuf);
465 			sdio_freerecvbuf(precvbuf);
466 			precvbuf++;
467 		}
468 		precvpriv->precv_buf = NULL;
469 	}
470 
471 	if (precvpriv->pallocated_recv_buf) {
472 		n = regsty->recvbuf_nr * sizeof(struct recv_buf) + 4;
473 		rtw_mfree(precvpriv->pallocated_recv_buf, n);
474 		precvpriv->pallocated_recv_buf = NULL;
475 	}
476 }
477