• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 
8 #include <drv_types.h>
9 #include <rtw_debug.h>
10 #include <rtl8723b_hal.h>
11 
rtw_sdio_wait_enough_TxOQT_space(struct adapter * padapter,u8 agg_num)12 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
13 {
14 	u32 n = 0;
15 	struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
16 
17 	while (pHalData->SdioTxOQTFreeSpace < agg_num) {
18 		if (
19 			(padapter->bSurpriseRemoved) ||
20 			(padapter->bDriverStopped)
21 		)
22 			return false;
23 
24 		HalQueryTxOQTBufferStatus8723BSdio(padapter);
25 
26 		if ((++n % 60) == 0) {
27 			msleep(1);
28 			/* yield(); */
29 		}
30 	}
31 
32 	pHalData->SdioTxOQTFreeSpace -= agg_num;
33 
34 	/* if (n > 1) */
35 	/* 	++priv->pshare->nr_out_of_txoqt_space; */
36 
37 	return true;
38 }
39 
rtl8723_dequeue_writeport(struct adapter * padapter)40 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
41 {
42 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
43 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
44 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
45 	struct xmit_buf *pxmitbuf;
46 	struct adapter *pri_padapter = padapter;
47 	s32 ret = 0;
48 	u8 PageIdx = 0;
49 	u32 deviceId;
50 	u8 bUpdatePageNum = false;
51 
52 	ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
53 
54 	if (ret)
55 		pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
56 	else
57 		pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
58 
59 	if (!pxmitbuf)
60 		return true;
61 
62 	deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
63 
64 	/*  translate fifo addr to queue index */
65 	switch (deviceId) {
66 	case WLAN_TX_HIQ_DEVICE_ID:
67 		PageIdx = HI_QUEUE_IDX;
68 		break;
69 
70 	case WLAN_TX_MIQ_DEVICE_ID:
71 		PageIdx = MID_QUEUE_IDX;
72 		break;
73 
74 	case WLAN_TX_LOQ_DEVICE_ID:
75 		PageIdx = LOW_QUEUE_IDX;
76 		break;
77 	}
78 
79 query_free_page:
80 	/*  check if hardware tx fifo page is enough */
81 	if (!rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
82 		if (!bUpdatePageNum) {
83 			/*  Total number of page is NOT available, so update current FIFO status */
84 			HalQueryTxBufferStatus8723BSdio(padapter);
85 			bUpdatePageNum = true;
86 			goto query_free_page;
87 		} else {
88 			bUpdatePageNum = false;
89 			enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
90 			return true;
91 		}
92 	}
93 
94 	if (
95 		(padapter->bSurpriseRemoved) ||
96 		(padapter->bDriverStopped)
97 	)
98 		goto free_xmitbuf;
99 
100 	if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
101 		goto free_xmitbuf;
102 
103 	traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
104 
105 	rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
106 
107 	rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
108 
109 free_xmitbuf:
110 	/* rtw_free_xmitframe(pxmitpriv, pframe); */
111 	/* pxmitbuf->priv_data = NULL; */
112 	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
113 
114 	return _FAIL;
115 }
116 
117 /*
118  * Description
119  *Transmit xmitbuf to hardware tx fifo
120  *
121  * Return
122  *_SUCCESS	ok
123  *_FAIL		something error
124  */
rtl8723bs_xmit_buf_handler(struct adapter * padapter)125 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
126 {
127 	struct xmit_priv *pxmitpriv;
128 	u8 queue_empty, queue_pending;
129 	s32 ret;
130 
131 
132 	pxmitpriv = &padapter->xmitpriv;
133 
134 	if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
135 		netdev_emerg(padapter->pnetdev,
136 			     "%s: down SdioXmitBufSema fail!\n", __func__);
137 		return _FAIL;
138 	}
139 
140 	ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
141 	if (ret)
142 		return _FAIL;
143 
144 	queue_pending = check_pending_xmitbuf(pxmitpriv);
145 
146 	if (!queue_pending)
147 		return _SUCCESS;
148 
149 	ret = rtw_register_tx_alive(padapter);
150 	if (ret != _SUCCESS) {
151 		return _SUCCESS;
152 	}
153 
154 	do {
155 		queue_empty = rtl8723_dequeue_writeport(padapter);
156 /* 	dump secondary adapter xmitbuf */
157 	} while (!queue_empty);
158 
159 	rtw_unregister_tx_alive(padapter);
160 
161 	return _SUCCESS;
162 }
163 
164 /*
165  * Description:
166  *Aggregation packets and send to hardware
167  *
168  * Return:
169  *0	Success
170  *-1	Hardware resource(TX FIFO) not ready
171  *-2	Software resource(xmitbuf) not ready
172  */
xmit_xmitframes(struct adapter * padapter,struct xmit_priv * pxmitpriv)173 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
174 {
175 	s32 err, ret;
176 	u32 k = 0;
177 	struct hw_xmit *hwxmits, *phwxmit;
178 	u8 idx, hwentry;
179 	struct tx_servq *ptxservq;
180 	struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp;
181 	struct xmit_frame *pxmitframe;
182 	struct __queue *pframe_queue;
183 	struct xmit_buf *pxmitbuf;
184 	u32 txlen, max_xmit_len;
185 	u8 txdesc_size = TXDESC_SIZE;
186 	int inx[4];
187 
188 	err = 0;
189 	hwxmits = pxmitpriv->hwxmits;
190 	hwentry = pxmitpriv->hwxmit_entry;
191 	ptxservq = NULL;
192 	pxmitframe = NULL;
193 	pframe_queue = NULL;
194 	pxmitbuf = NULL;
195 
196 	if (padapter->registrypriv.wifi_spec == 1) {
197 		for (idx = 0; idx < 4; idx++)
198 			inx[idx] = pxmitpriv->wmm_para_seq[idx];
199 	} else {
200 		inx[0] = 0;
201 		inx[1] = 1;
202 		inx[2] = 2;
203 		inx[3] = 3;
204 	}
205 
206 	/*  0(VO), 1(VI), 2(BE), 3(BK) */
207 	for (idx = 0; idx < hwentry; idx++) {
208 		phwxmit = hwxmits + inx[idx];
209 
210 		if (
211 			(check_pending_xmitbuf(pxmitpriv)) &&
212 			(padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
213 		) {
214 			if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
215 				err = -2;
216 				break;
217 			}
218 		}
219 
220 		max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
221 
222 		spin_lock_bh(&pxmitpriv->lock);
223 
224 		sta_phead = get_list_head(phwxmit->sta_queue);
225 		/* because stop_sta_xmit may delete sta_plist at any time */
226 		/* so we should add lock here, or while loop can not exit */
227 		list_for_each_safe(sta_plist, tmp, sta_phead) {
228 			ptxservq = list_entry(sta_plist, struct tx_servq,
229 					      tx_pending);
230 
231 			pframe_queue = &ptxservq->sta_pending;
232 
233 			frame_phead = get_list_head(pframe_queue);
234 
235 			while (list_empty(frame_phead) == false) {
236 				frame_plist = get_next(frame_phead);
237 				pxmitframe = container_of(frame_plist, struct xmit_frame, list);
238 
239 				/*  check xmit_buf size enough or not */
240 				txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
241 				if (!pxmitbuf ||
242 					((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
243 					(k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
244 				) {
245 					if (pxmitbuf) {
246 						/* pxmitbuf->priv_data will be NULL, and will crash here */
247 						if (pxmitbuf->len > 0 &&
248 						    pxmitbuf->priv_data) {
249 							struct xmit_frame *pframe;
250 							pframe = (struct xmit_frame *)pxmitbuf->priv_data;
251 							pframe->agg_num = k;
252 							pxmitbuf->agg_num = k;
253 							rtl8723b_update_txdesc(pframe, pframe->buf_addr);
254 							rtw_free_xmitframe(pxmitpriv, pframe);
255 							pxmitbuf->priv_data = NULL;
256 							enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
257 							/* can not yield under lock */
258 							/* yield(); */
259 						} else
260 							rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
261 					}
262 
263 					pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
264 					if (!pxmitbuf) {
265 #ifdef DBG_XMIT_BUF
266 						netdev_err(padapter->pnetdev,
267 							   "%s: xmit_buf is not enough!\n",
268 							   __func__);
269 #endif
270 						err = -2;
271 						complete(&(pxmitpriv->xmit_comp));
272 						break;
273 					}
274 					k = 0;
275 				}
276 
277 				/*  ok to send, remove frame from queue */
278 				if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
279 					if (
280 						(pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
281 						(pxmitframe->attrib.triggered == 0)
282 					)
283 						break;
284 
285 				list_del_init(&pxmitframe->list);
286 				ptxservq->qcnt--;
287 				phwxmit->accnt--;
288 
289 				if (k == 0) {
290 					pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
291 					pxmitbuf->priv_data = (u8 *)pxmitframe;
292 				}
293 
294 				/*  coalesce the xmitframe to xmitbuf */
295 				pxmitframe->pxmitbuf = pxmitbuf;
296 				pxmitframe->buf_addr = pxmitbuf->ptail;
297 
298 				ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
299 				if (ret == _FAIL) {
300 					netdev_err(padapter->pnetdev,
301 						   "%s: coalesce FAIL!",
302 						   __func__);
303 					/*  Todo: error handler */
304 				} else {
305 					k++;
306 					if (k != 1)
307 						rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
308 					rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
309 
310 					txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
311 					pxmitframe->pg_num = (txlen + 127) / 128;
312 					pxmitbuf->pg_num += (txlen + 127) / 128;
313 				    /* if (k != 1) */
314 					/* 	((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
315 					pxmitbuf->ptail += _RND(txlen, 8); /*  round to 8 bytes alignment */
316 					pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
317 				}
318 
319 				if (k != 1)
320 					rtw_free_xmitframe(pxmitpriv, pxmitframe);
321 				pxmitframe = NULL;
322 			}
323 
324 			if (list_empty(&pframe_queue->queue))
325 				list_del_init(&ptxservq->tx_pending);
326 
327 			if (err)
328 				break;
329 		}
330 		spin_unlock_bh(&pxmitpriv->lock);
331 
332 		/*  dump xmit_buf to hw tx fifo */
333 		if (pxmitbuf) {
334 			if (pxmitbuf->len > 0) {
335 				struct xmit_frame *pframe;
336 				pframe = (struct xmit_frame *)pxmitbuf->priv_data;
337 				pframe->agg_num = k;
338 				pxmitbuf->agg_num = k;
339 				rtl8723b_update_txdesc(pframe, pframe->buf_addr);
340 				rtw_free_xmitframe(pxmitpriv, pframe);
341 				pxmitbuf->priv_data = NULL;
342 				enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
343 				yield();
344 			} else
345 				rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
346 			pxmitbuf = NULL;
347 		}
348 
349 		if (err)
350 			break;
351 	}
352 
353 	return err;
354 }
355 
356 /*
357  * Description
358  *Transmit xmitframe from queue
359  *
360  * Return
361  *_SUCCESS	ok
362  *_FAIL		something error
363  */
rtl8723bs_xmit_handler(struct adapter * padapter)364 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
365 {
366 	struct xmit_priv *pxmitpriv;
367 	s32 ret;
368 
369 
370 	pxmitpriv = &padapter->xmitpriv;
371 
372 	if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
373 		netdev_emerg(padapter->pnetdev, "%s: SdioXmitStart fail!\n",
374 			     __func__);
375 		return _FAIL;
376 	}
377 
378 next:
379 	if (
380 		(padapter->bDriverStopped) ||
381 		(padapter->bSurpriseRemoved)
382 	)
383 		return _FAIL;
384 
385 	spin_lock_bh(&pxmitpriv->lock);
386 	ret = rtw_txframes_pending(padapter);
387 	spin_unlock_bh(&pxmitpriv->lock);
388 	if (ret == 0) {
389 		return _SUCCESS;
390 	}
391 
392 	/*  dequeue frame and write to hardware */
393 
394 	ret = xmit_xmitframes(padapter, pxmitpriv);
395 	if (ret == -2) {
396 		/* here sleep 1ms will cause big TP loss of TX */
397 		/* from 50+ to 40+ */
398 		if (padapter->registrypriv.wifi_spec)
399 			msleep(1);
400 		else
401 			yield();
402 		goto next;
403 	}
404 
405 	spin_lock_bh(&pxmitpriv->lock);
406 	ret = rtw_txframes_pending(padapter);
407 	spin_unlock_bh(&pxmitpriv->lock);
408 	if (ret == 1) {
409 		goto next;
410 	}
411 
412 	return _SUCCESS;
413 }
414 
rtl8723bs_xmit_thread(void * context)415 int rtl8723bs_xmit_thread(void *context)
416 {
417 	s32 ret;
418 	struct adapter *padapter;
419 	struct xmit_priv *pxmitpriv;
420 	u8 thread_name[20];
421 
422 	ret = _SUCCESS;
423 	padapter = context;
424 	pxmitpriv = &padapter->xmitpriv;
425 
426 	rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
427 	thread_enter(thread_name);
428 
429 	do {
430 		ret = rtl8723bs_xmit_handler(padapter);
431 		if (signal_pending(current)) {
432 			flush_signals(current);
433 		}
434 	} while (_SUCCESS == ret);
435 
436 	complete(&pxmitpriv->SdioXmitTerminate);
437 
438 	thread_exit();
439 }
440 
rtl8723bs_mgnt_xmit(struct adapter * padapter,struct xmit_frame * pmgntframe)441 s32 rtl8723bs_mgnt_xmit(
442 	struct adapter *padapter, struct xmit_frame *pmgntframe
443 )
444 {
445 	s32 ret = _SUCCESS;
446 	struct pkt_attrib *pattrib;
447 	struct xmit_buf *pxmitbuf;
448 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
449 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
450 	u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
451 	u8 txdesc_size = TXDESC_SIZE;
452 
453 	pattrib = &pmgntframe->attrib;
454 	pxmitbuf = pmgntframe->pxmitbuf;
455 
456 	rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
457 
458 	pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
459 	pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /*  128 is tx page size */
460 	pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
461 	pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
462 
463 	rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
464 
465 	rtw_free_xmitframe(pxmitpriv, pmgntframe);
466 
467 	pxmitbuf->priv_data = NULL;
468 
469 	if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
470 		ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
471 		if (ret != _SUCCESS)
472 			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
473 
474 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
475 	} else
476 		enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
477 
478 	return ret;
479 }
480 
481 /*
482  * Description:
483  *Handle xmitframe(packet) come from rtw_xmit()
484  *
485  * Return:
486  *true	dump packet directly ok
487  *false	enqueue, temporary can't transmit packets to hardware
488  */
rtl8723bs_hal_xmit(struct adapter * padapter,struct xmit_frame * pxmitframe)489 s32 rtl8723bs_hal_xmit(
490 	struct adapter *padapter, struct xmit_frame *pxmitframe
491 )
492 {
493 	struct xmit_priv *pxmitpriv;
494 	s32 err;
495 
496 
497 	pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
498 	pxmitpriv = &padapter->xmitpriv;
499 
500 	if (
501 		(pxmitframe->frame_tag == DATA_FRAMETAG) &&
502 		(pxmitframe->attrib.ether_type != 0x0806) &&
503 		(pxmitframe->attrib.ether_type != 0x888e) &&
504 		(pxmitframe->attrib.dhcp_pkt != 1)
505 	) {
506 		if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
507 			rtw_issue_addbareq_cmd(padapter, pxmitframe);
508 	}
509 
510 	spin_lock_bh(&pxmitpriv->lock);
511 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
512 	spin_unlock_bh(&pxmitpriv->lock);
513 	if (err != _SUCCESS) {
514 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
515 
516 		pxmitpriv->tx_drop++;
517 		return true;
518 	}
519 
520 	complete(&pxmitpriv->SdioXmitStart);
521 
522 	return false;
523 }
524 
rtl8723bs_hal_xmitframe_enqueue(struct adapter * padapter,struct xmit_frame * pxmitframe)525 s32	rtl8723bs_hal_xmitframe_enqueue(
526 	struct adapter *padapter, struct xmit_frame *pxmitframe
527 )
528 {
529 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
530 	s32 err;
531 
532 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
533 	if (err != _SUCCESS) {
534 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
535 
536 		pxmitpriv->tx_drop++;
537 	} else {
538 		complete(&pxmitpriv->SdioXmitStart);
539 	}
540 
541 	return err;
542 
543 }
544 
545 /*
546  * Return
547  *_SUCCESS	start thread ok
548  *_FAIL		start thread fail
549  *
550  */
rtl8723bs_init_xmit_priv(struct adapter * padapter)551 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
552 {
553 	struct xmit_priv *xmitpriv = &padapter->xmitpriv;
554 	struct hal_com_data *phal;
555 
556 
557 	phal = GET_HAL_DATA(padapter);
558 
559 	spin_lock_init(&phal->SdioTxFIFOFreePageLock);
560 	init_completion(&xmitpriv->SdioXmitStart);
561 	init_completion(&xmitpriv->SdioXmitTerminate);
562 
563 	return _SUCCESS;
564 }
565 
rtl8723bs_free_xmit_priv(struct adapter * padapter)566 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
567 {
568 	struct xmit_priv *pxmitpriv;
569 	struct xmit_buf *pxmitbuf;
570 	struct __queue *pqueue;
571 	struct list_head *plist, *phead;
572 	struct list_head tmplist;
573 
574 
575 	pxmitpriv = &padapter->xmitpriv;
576 	pqueue = &pxmitpriv->pending_xmitbuf_queue;
577 	phead = get_list_head(pqueue);
578 	INIT_LIST_HEAD(&tmplist);
579 
580 	spin_lock_bh(&pqueue->lock);
581 	if (!list_empty(&pqueue->queue)) {
582 		/*  Insert tmplist to end of queue, and delete phead */
583 		/*  then tmplist become head of queue. */
584 		list_add_tail(&tmplist, phead);
585 		list_del_init(phead);
586 	}
587 	spin_unlock_bh(&pqueue->lock);
588 
589 	phead = &tmplist;
590 	while (list_empty(phead) == false) {
591 		plist = get_next(phead);
592 		list_del_init(plist);
593 
594 		pxmitbuf = container_of(plist, struct xmit_buf, list);
595 		rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
596 		pxmitbuf->priv_data = NULL;
597 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
598 	}
599 }
600