xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_txrx_legacy_flow_control.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* OS abstraction libraries */
19 #include <qdf_nbuf.h>           /* qdf_nbuf_t, etc. */
20 #include <qdf_atomic.h>         /* qdf_atomic_read, etc. */
21 #include <qdf_util.h>           /* qdf_unlikely */
22 
23 /* APIs for other modules */
24 #include <htt.h>                /* HTT_TX_EXT_TID_MGMT */
25 #include <ol_htt_tx_api.h>      /* htt_tx_desc_tid */
26 
27 /* internal header files relevant for all systems */
28 #include <ol_txrx_internal.h>   /* TXRX_ASSERT1 */
29 #include <ol_tx_desc.h>         /* ol_tx_desc */
30 #include <ol_tx_send.h>         /* ol_tx_send */
31 #include <ol_txrx.h>            /* ol_txrx_get_vdev_from_vdev_id */
32 
33 /* internal header files relevant only for HL systems */
34 #include <ol_tx_queue.h>        /* ol_tx_enqueue */
35 
36 /* internal header files relevant only for specific systems (Pronto) */
37 #include <ol_txrx_encap.h>      /* OL_TX_ENCAP, etc */
38 #include <ol_tx.h>
39 #include <ol_cfg.h>
40 #include <cdp_txrx_handle.h>
41 
ol_txrx_vdev_pause(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint32_t reason,uint32_t pause_type)42 void ol_txrx_vdev_pause(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
43 			uint32_t reason, uint32_t pause_type)
44 {
45 	struct ol_txrx_vdev_t *vdev =
46 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
47 
48 	if (qdf_unlikely(!vdev)) {
49 		ol_txrx_err("vdev is NULL");
50 		return;
51 	}
52 
53 	/* TO DO: log the queue pause */
54 	/* acquire the mutex lock, since we'll be modifying the queues */
55 	TX_SCHED_DEBUG_PRINT("Enter");
56 
57 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
58 	vdev->ll_pause.paused_reason |= reason;
59 	vdev->ll_pause.q_pause_cnt++;
60 	vdev->ll_pause.is_q_paused = true;
61 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
62 
63 	TX_SCHED_DEBUG_PRINT("Leave");
64 }
65 
ol_txrx_vdev_unpause(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,uint32_t reason,uint32_t pause_type)66 void ol_txrx_vdev_unpause(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
67 			  uint32_t reason, uint32_t pause_type)
68 {
69 	struct ol_txrx_vdev_t *vdev =
70 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
71 
72 	if (qdf_unlikely(!vdev)) {
73 		ol_txrx_err("vdev is NULL");
74 		return;
75 	}
76 
77 	/* TO DO: log the queue unpause */
78 	/* acquire the mutex lock, since we'll be modifying the queues */
79 	TX_SCHED_DEBUG_PRINT("Enter");
80 
81 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
82 	if (vdev->ll_pause.paused_reason & reason) {
83 		vdev->ll_pause.paused_reason &= ~reason;
84 		if (!vdev->ll_pause.paused_reason) {
85 			vdev->ll_pause.is_q_paused = false;
86 			vdev->ll_pause.q_unpause_cnt++;
87 			qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
88 			ol_tx_vdev_ll_pause_queue_send((void *)vdev);
89 		} else {
90 			qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
91 		}
92 	} else {
93 		qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
94 	}
95 	TX_SCHED_DEBUG_PRINT("Leave");
96 }
97 
ol_txrx_vdev_flush(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)98 void ol_txrx_vdev_flush(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
99 {
100 	struct ol_txrx_vdev_t *vdev =
101 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
102 
103 	if (qdf_unlikely(!vdev)) {
104 		ol_txrx_err("vdev is NULL");
105 		return;
106 	}
107 
108 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
109 	qdf_timer_stop(&vdev->ll_pause.timer);
110 	vdev->ll_pause.is_q_timer_on = false;
111 	while (vdev->ll_pause.txq.head) {
112 		qdf_nbuf_t next =
113 			qdf_nbuf_next(vdev->ll_pause.txq.head);
114 		qdf_nbuf_set_next(vdev->ll_pause.txq.head, NULL);
115 		if (QDF_NBUF_CB_PADDR(vdev->ll_pause.txq.head)) {
116 			if (!qdf_nbuf_ipa_owned_get(vdev->ll_pause.txq.head))
117 				qdf_nbuf_unmap(vdev->pdev->osdev,
118 					       vdev->ll_pause.txq.head,
119 					       QDF_DMA_TO_DEVICE);
120 		}
121 		qdf_nbuf_tx_free(vdev->ll_pause.txq.head,
122 				 QDF_NBUF_PKT_ERROR);
123 		vdev->ll_pause.txq.head = next;
124 	}
125 	vdev->ll_pause.txq.tail = NULL;
126 	vdev->ll_pause.txq.depth = 0;
127 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
128 }
129 
130 #define OL_TX_VDEV_PAUSE_QUEUE_SEND_MARGIN 400
131 #define OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS 5
132 
133 #define OL_TX_THROTTLE_MAX_SEND_LEVEL1 80
134 #define OL_TX_THROTTLE_MAX_SEND_LEVEL2 65
135 #define OL_TX_THROTTLE_MAX_SEND_LEVEL3 55
136 #define OL_TX_THROTTLE_MAX_SEND_LEVEL4 45
137 #define OL_TX_THROTTLE_MAX_SEND_LEVEL5 35
138 #define OL_TX_THROTTLE_MAX_SEND_LEVEL6 20
139 #define OL_TX_THROTTLE_MAX_SEND_LEVEL7 10
140 #define OL_TX_THROTTLE_MAX_SEND_LEVEL8 5
141 #define OL_TX_THROTTLE_MAX_SEND_LEVEL9 1
142 
143 /**
144  * ol_tx_get_max_to_send() - Get the maximum number of packets
145  * that can be sent for different phy rate
146  * @pdev: datapath pdev handle
147  *
148  * Return: int type value
149  */
ol_tx_get_max_to_send(struct ol_txrx_pdev_t * pdev)150 static int ol_tx_get_max_to_send(struct ol_txrx_pdev_t *pdev)
151 {
152 	uint16_t consume_num_last_timer;
153 	int max_to_send;
154 
155 	qdf_spin_lock_bh(&pdev->tx_mutex);
156 	if (!pdev->tx_throttle.prev_outstanding_num) {
157 		max_to_send = OL_TX_THROTTLE_MAX_SEND_LEVEL5;
158 	} else {
159 		consume_num_last_timer =
160 			(pdev->tx_throttle.prev_outstanding_num -
161 			 pdev->tx_desc.pool_size +
162 			 pdev->tx_desc.num_free);
163 		if (consume_num_last_timer >=
164 			OL_TX_THROTTLE_MAX_SEND_LEVEL1) {
165 			max_to_send = pdev->tx_throttle.tx_threshold;
166 		} else if (consume_num_last_timer >=
167 				OL_TX_THROTTLE_MAX_SEND_LEVEL2) {
168 			max_to_send =
169 				OL_TX_THROTTLE_MAX_SEND_LEVEL1;
170 		} else if (consume_num_last_timer >=
171 				OL_TX_THROTTLE_MAX_SEND_LEVEL3) {
172 			max_to_send =
173 				OL_TX_THROTTLE_MAX_SEND_LEVEL2;
174 		} else if (consume_num_last_timer >=
175 				OL_TX_THROTTLE_MAX_SEND_LEVEL4) {
176 			max_to_send =
177 				OL_TX_THROTTLE_MAX_SEND_LEVEL3;
178 		} else if (consume_num_last_timer >=
179 				OL_TX_THROTTLE_MAX_SEND_LEVEL5) {
180 			max_to_send =
181 				OL_TX_THROTTLE_MAX_SEND_LEVEL4;
182 		} else if (pdev->tx_throttle.prev_outstanding_num >
183 				consume_num_last_timer) {
184 			/*
185 			 * when TX packet number is smaller than 35,
186 			 * most likely low phy rate is being used.
187 			 * As long as pdev->tx_throttle.prev_outstanding_num
188 			 * is greater than consume_num_last_timer, it
189 			 * means small TX packet number isn't limited
190 			 * by packets injected from host.
191 			 */
192 			if (consume_num_last_timer >=
193 				OL_TX_THROTTLE_MAX_SEND_LEVEL6)
194 				max_to_send =
195 					OL_TX_THROTTLE_MAX_SEND_LEVEL6;
196 			else if (consume_num_last_timer >=
197 					OL_TX_THROTTLE_MAX_SEND_LEVEL7)
198 				max_to_send =
199 					OL_TX_THROTTLE_MAX_SEND_LEVEL7;
200 			else if (consume_num_last_timer >=
201 					OL_TX_THROTTLE_MAX_SEND_LEVEL8)
202 				max_to_send =
203 					OL_TX_THROTTLE_MAX_SEND_LEVEL8;
204 			else
205 				max_to_send =
206 					OL_TX_THROTTLE_MAX_SEND_LEVEL9;
207 		} else {
208 			/*
209 			 * when come here, it means it's hard to evaluate
210 			 * current phy rate, for safety, max_to_send set
211 			 * to OL_TX_THROTTLE_MAX_SEND_LEVEL5.
212 			 */
213 			max_to_send = OL_TX_THROTTLE_MAX_SEND_LEVEL5;
214 		}
215 	}
216 	qdf_spin_unlock_bh(&pdev->tx_mutex);
217 
218 	return max_to_send;
219 }
220 
ol_tx_vdev_ll_pause_queue_send_base(struct ol_txrx_vdev_t * vdev)221 static void ol_tx_vdev_ll_pause_queue_send_base(struct ol_txrx_vdev_t *vdev)
222 {
223 	int max_to_accept;
224 
225 	if (!vdev)
226 		return;
227 
228 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
229 	if (vdev->ll_pause.paused_reason) {
230 		qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
231 		return;
232 	}
233 
234 	/*
235 	 * Send as much of the backlog as possible, but leave some margin
236 	 * of unallocated tx descriptors that can be used for new frames
237 	 * being transmitted by other vdevs.
238 	 * Ideally there would be a scheduler, which would not only leave
239 	 * some margin for new frames for other vdevs, but also would
240 	 * fairly apportion the tx descriptors between multiple vdevs that
241 	 * have backlogs in their pause queues.
242 	 * However, the fairness benefit of having a scheduler for frames
243 	 * from multiple vdev's pause queues is not sufficient to outweigh
244 	 * the extra complexity.
245 	 */
246 	max_to_accept = vdev->pdev->tx_desc.num_free -
247 		OL_TX_VDEV_PAUSE_QUEUE_SEND_MARGIN;
248 	while (max_to_accept > 0 && vdev->ll_pause.txq.depth) {
249 		qdf_nbuf_t tx_msdu;
250 
251 		max_to_accept--;
252 		vdev->ll_pause.txq.depth--;
253 		tx_msdu = vdev->ll_pause.txq.head;
254 		if (tx_msdu) {
255 			vdev->ll_pause.txq.head = qdf_nbuf_next(tx_msdu);
256 			if (!vdev->ll_pause.txq.head)
257 				vdev->ll_pause.txq.tail = NULL;
258 			qdf_nbuf_set_next(tx_msdu, NULL);
259 			QDF_NBUF_UPDATE_TX_PKT_COUNT(tx_msdu,
260 						QDF_NBUF_TX_PKT_TXRX_DEQUEUE);
261 			tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu);
262 			/*
263 			 * It is unexpected that ol_tx_ll would reject the frame
264 			 * since we checked that there's room for it, though
265 			 * there's an infinitesimal possibility that between the
266 			 * time we checked the room available and now, a
267 			 * concurrent batch of tx frames used up all the room.
268 			 * For simplicity, just drop the frame.
269 			 */
270 			if (tx_msdu) {
271 				qdf_nbuf_unmap(vdev->pdev->osdev, tx_msdu,
272 					       QDF_DMA_TO_DEVICE);
273 				qdf_nbuf_tx_free(tx_msdu, QDF_NBUF_PKT_ERROR);
274 			}
275 		}
276 	}
277 	if (vdev->ll_pause.txq.depth) {
278 		qdf_timer_stop(&vdev->ll_pause.timer);
279 		if (!qdf_atomic_read(&vdev->delete.detaching)) {
280 			qdf_timer_start(&vdev->ll_pause.timer,
281 					OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS);
282 			vdev->ll_pause.is_q_timer_on = true;
283 		}
284 		if (vdev->ll_pause.txq.depth >= vdev->ll_pause.max_q_depth)
285 			vdev->ll_pause.q_overflow_cnt++;
286 	}
287 
288 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
289 }
290 
291 static qdf_nbuf_t
ol_tx_vdev_pause_queue_append(struct ol_txrx_vdev_t * vdev,qdf_nbuf_t msdu_list,uint8_t start_timer)292 ol_tx_vdev_pause_queue_append(struct ol_txrx_vdev_t *vdev,
293 			      qdf_nbuf_t msdu_list, uint8_t start_timer)
294 {
295 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
296 	while (msdu_list &&
297 	       vdev->ll_pause.txq.depth < vdev->ll_pause.max_q_depth) {
298 		qdf_nbuf_t next = qdf_nbuf_next(msdu_list);
299 
300 		QDF_NBUF_UPDATE_TX_PKT_COUNT(msdu_list,
301 					     QDF_NBUF_TX_PKT_TXRX_ENQUEUE);
302 		DPTRACE(qdf_dp_trace(msdu_list,
303 			QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD,
304 			QDF_TRACE_DEFAULT_PDEV_ID,
305 			qdf_nbuf_data_addr(msdu_list),
306 			sizeof(qdf_nbuf_data(msdu_list)), QDF_TX));
307 
308 		vdev->ll_pause.txq.depth++;
309 		if (!vdev->ll_pause.txq.head) {
310 			vdev->ll_pause.txq.head = msdu_list;
311 			vdev->ll_pause.txq.tail = msdu_list;
312 		} else {
313 			qdf_nbuf_set_next(vdev->ll_pause.txq.tail, msdu_list);
314 		}
315 		vdev->ll_pause.txq.tail = msdu_list;
316 
317 		msdu_list = next;
318 	}
319 	if (vdev->ll_pause.txq.tail)
320 		qdf_nbuf_set_next(vdev->ll_pause.txq.tail, NULL);
321 
322 	if (start_timer) {
323 		qdf_timer_stop(&vdev->ll_pause.timer);
324 		if (!qdf_atomic_read(&vdev->delete.detaching)) {
325 			qdf_timer_start(&vdev->ll_pause.timer,
326 					OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS);
327 			vdev->ll_pause.is_q_timer_on = true;
328 		}
329 	}
330 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
331 
332 	return msdu_list;
333 }
334 
335 /*
336  * Store up the tx frame in the vdev's tx queue if the vdev is paused.
337  * If there are too many frames in the tx queue, reject it.
338  */
ol_tx_ll_queue(ol_txrx_vdev_handle vdev,qdf_nbuf_t msdu_list)339 qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
340 {
341 	uint16_t eth_type;
342 	uint32_t paused_reason;
343 
344 	if (!msdu_list)
345 		return NULL;
346 
347 	paused_reason = vdev->ll_pause.paused_reason;
348 	if (paused_reason) {
349 		if (qdf_unlikely((paused_reason &
350 				  OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED) ==
351 				 paused_reason)) {
352 			eth_type = (((struct ethernet_hdr_t *)
353 				     qdf_nbuf_data(msdu_list))->
354 				    ethertype[0] << 8) |
355 				   (((struct ethernet_hdr_t *)
356 				     qdf_nbuf_data(msdu_list))->ethertype[1]);
357 			if (ETHERTYPE_IS_EAPOL_WAPI(eth_type)) {
358 				msdu_list = ol_tx_ll_wrapper(vdev, msdu_list);
359 				return msdu_list;
360 			}
361 		}
362 		msdu_list = ol_tx_vdev_pause_queue_append(vdev, msdu_list, 1);
363 	} else {
364 		if (vdev->ll_pause.txq.depth > 0 ||
365 		    vdev->pdev->tx_throttle.current_throttle_level !=
366 		    THROTTLE_LEVEL_0) {
367 			/*
368 			 * not paused, but there is a backlog of frms
369 			 * from a prior pause or throttle off phase
370 			 */
371 			msdu_list = ol_tx_vdev_pause_queue_append(
372 				vdev, msdu_list, 0);
373 			/*
374 			 * if throttle is disabled or phase is "on",
375 			 * send the frame
376 			 */
377 			if (vdev->pdev->tx_throttle.current_throttle_level ==
378 			    THROTTLE_LEVEL_0) {
379 				/*
380 				 * send as many frames as possible
381 				 * from the vdevs backlog
382 				 */
383 				ol_tx_vdev_ll_pause_queue_send_base(vdev);
384 			}
385 		} else {
386 			/*
387 			 * not paused, no throttle and no backlog -
388 			 * send the new frames
389 			 */
390 			msdu_list = ol_tx_ll_wrapper(vdev, msdu_list);
391 		}
392 	}
393 	return msdu_list;
394 }
395 
396 /*
397  * Run through the transmit queues for all the vdevs and
398  * send the pending frames
399  */
ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t * pdev)400 void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev)
401 {
402 	int max_to_send;        /* tracks how many frames have been sent */
403 	qdf_nbuf_t tx_msdu;
404 	struct ol_txrx_vdev_t *vdev = NULL;
405 	uint8_t more;
406 
407 	if (!pdev)
408 		return;
409 
410 	if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF)
411 		return;
412 
413 	/*
414 	 * For host implementation thermal mitigation, there has limitation
415 	 * in low phy rate case, like 11A 6M, 11B 11M. Host may have entered
416 	 * throttle off state, if a big number packets are queued to ring
417 	 * buffer in low phy rate, FW will have to keep active state during
418 	 * the whole throttle cycle. So you need to be careful when
419 	 * configuring the max_to_send value to avoid the chip temperature
420 	 * suddenly rises to very high in high temperature test.
421 	 * So add variable prev_outstanding_num to save last time outstanding
422 	 * number, when pdev->tx_throttle.tx_timer come again, we can check
423 	 * the gap to know high or low phy rate is being used, then choose
424 	 * right max_to_send.
425 	 * When it's the first time to enter the function, there doesn't have
426 	 * info for prev_outstanding_num, to satisfy all rate, the maximum
427 	 * safe number is OL_TX_THROTTLE_MAX_SEND_LEVEL5(35).
428 	 */
429 	max_to_send = ol_tx_get_max_to_send(pdev);
430 
431 	/* round robin through the vdev queues for the given pdev */
432 
433 	/*
434 	 * Potential improvement: download several frames from the same vdev
435 	 * at a time, since it is more likely that those frames could be
436 	 * aggregated together, remember which vdev was serviced last,
437 	 * so the next call this function can resume the round-robin
438 	 * traversing where the current invocation left off
439 	 */
440 	do {
441 		more = 0;
442 		TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
443 			qdf_spin_lock_bh(&vdev->ll_pause.mutex);
444 			if (vdev->ll_pause.txq.depth) {
445 				if (vdev->ll_pause.paused_reason) {
446 					qdf_spin_unlock_bh(&vdev->ll_pause.
447 							   mutex);
448 					continue;
449 				}
450 
451 				tx_msdu = vdev->ll_pause.txq.head;
452 				if (!tx_msdu) {
453 					qdf_spin_unlock_bh(&vdev->ll_pause.
454 							   mutex);
455 					continue;
456 				}
457 
458 				max_to_send--;
459 				vdev->ll_pause.txq.depth--;
460 
461 				vdev->ll_pause.txq.head =
462 					qdf_nbuf_next(tx_msdu);
463 
464 				if (!vdev->ll_pause.txq.head)
465 					vdev->ll_pause.txq.tail = NULL;
466 
467 				qdf_nbuf_set_next(tx_msdu, NULL);
468 				tx_msdu = ol_tx_ll_wrapper(vdev, tx_msdu);
469 				/*
470 				 * It is unexpected that ol_tx_ll would reject
471 				 * the frame, since we checked that there's
472 				 * room for it, though there's an infinitesimal
473 				 * possibility that between the time we checked
474 				 * the room available and now, a concurrent
475 				 * batch of tx frames used up all the room.
476 				 * For simplicity, just drop the frame.
477 				 */
478 				if (tx_msdu) {
479 					qdf_nbuf_unmap(pdev->osdev, tx_msdu,
480 						       QDF_DMA_TO_DEVICE);
481 					qdf_nbuf_tx_free(tx_msdu,
482 							 QDF_NBUF_PKT_ERROR);
483 				}
484 			}
485 			/*check if there are more msdus to transmit */
486 			if (vdev->ll_pause.txq.depth)
487 				more = 1;
488 			qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
489 		}
490 	} while (more && max_to_send);
491 
492 	qdf_spin_lock_bh(&pdev->tx_mutex);
493 	pdev->tx_throttle.prev_outstanding_num =
494 		(pdev->tx_desc.pool_size - pdev->tx_desc.num_free);
495 	qdf_spin_unlock_bh(&pdev->tx_mutex);
496 
497 	/*
498 	 * currently as long as pdev->tx_throttle.current_throttle_level
499 	 * isn't THROTTLE_LEVEL_0, all TX data is scheduled by Tx
500 	 * throttle. It's needed to always start pdev->tx_throttle.tx_timer
501 	 * at the end of each TX throttle processing to avoid TX cannot be
502 	 * scheduled in the remaining throttle_on time.
503 	 */
504 	qdf_timer_stop(&pdev->tx_throttle.tx_timer);
505 	qdf_timer_start(&pdev->tx_throttle.tx_timer,
506 			OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS);
507 }
508 
ol_tx_vdev_ll_pause_queue_send(void * context)509 void ol_tx_vdev_ll_pause_queue_send(void *context)
510 {
511 	struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)context;
512 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
513 
514 	if (pdev &&
515 	    pdev->tx_throttle.current_throttle_level != THROTTLE_LEVEL_0)
516 		return;
517 	ol_tx_vdev_ll_pause_queue_send_base(vdev);
518 }
519 
ol_txrx_register_tx_flow_control(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,ol_txrx_tx_flow_control_fp flowControl,void * osif_fc_ctx,ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause)520 int ol_txrx_register_tx_flow_control(struct cdp_soc_t *soc_hdl,
521 				     uint8_t vdev_id,
522 				     ol_txrx_tx_flow_control_fp flowControl,
523 				     void *osif_fc_ctx,
524 				     ol_txrx_tx_flow_control_is_pause_fp
525 				     flow_control_is_pause)
526 {
527 	struct ol_txrx_vdev_t *vdev =
528 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
529 
530 	if (!vdev) {
531 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
532 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
533 		return -EINVAL;
534 	}
535 
536 	qdf_spin_lock_bh(&vdev->flow_control_lock);
537 	vdev->osif_flow_control_cb = flowControl;
538 	vdev->osif_flow_control_is_pause = flow_control_is_pause;
539 	vdev->osif_fc_ctx = osif_fc_ctx;
540 	qdf_spin_unlock_bh(&vdev->flow_control_lock);
541 	return 0;
542 }
543 
ol_txrx_deregister_tx_flow_control_cb(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)544 int ol_txrx_deregister_tx_flow_control_cb(struct cdp_soc_t *soc_hdl,
545 					  uint8_t vdev_id)
546 {
547 	struct ol_txrx_vdev_t *vdev =
548 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
549 
550 	if (!vdev) {
551 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
552 			  "%s: Invalid vdev_id", __func__);
553 		return -EINVAL;
554 	}
555 
556 	qdf_spin_lock_bh(&vdev->flow_control_lock);
557 	vdev->osif_flow_control_cb = NULL;
558 	vdev->osif_flow_control_is_pause = NULL;
559 	vdev->osif_fc_ctx = NULL;
560 	qdf_spin_unlock_bh(&vdev->flow_control_lock);
561 	return 0;
562 }
563 
564 /**
565  * ol_txrx_get_tx_resource() - if tx resource less than low_watermark
566  * soc_hdl: soc handle
567  * @pdev_id: datapath pdev identifier
568  * @peer_addr: peer mac address
569  * @low_watermark: low watermark
570  * @high_watermark_offset: high watermark offset value
571  *
572  * Return: true/false
573  */
574 bool
ol_txrx_get_tx_resource(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,struct qdf_mac_addr peer_addr,unsigned int low_watermark,unsigned int high_watermark_offset)575 ol_txrx_get_tx_resource(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
576 			struct qdf_mac_addr peer_addr,
577 			unsigned int low_watermark,
578 			unsigned int high_watermark_offset)
579 {
580 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
581 	ol_txrx_pdev_handle pdev =
582 				ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
583 	ol_txrx_vdev_handle vdev;
584 
585 	if (qdf_unlikely(!pdev)) {
586 		ol_txrx_err("pdev is NULL");
587 		return true;
588 	}
589 
590 	vdev = ol_txrx_get_vdev_by_peer_addr(ol_txrx_pdev_t_to_cdp_pdev(pdev),
591 					     peer_addr);
592 	if (!vdev) {
593 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
594 			  "%s: Invalid peer address: " QDF_MAC_ADDR_FMT,
595 			  __func__, QDF_MAC_ADDR_REF(peer_addr.bytes));
596 		/* Return true so caller do not understand that resource
597 		 * is less than low_watermark.
598 		 * sta_id validation will be done in ol_tx_send_data_frame
599 		 * and if sta_id is not registered then host will drop
600 		 * packet.
601 		 */
602 		return true;
603 	}
604 
605 	qdf_spin_lock_bh(&vdev->pdev->tx_mutex);
606 
607 	if (vdev->pdev->tx_desc.num_free < (uint16_t)low_watermark) {
608 		vdev->tx_fl_lwm = (uint16_t)low_watermark;
609 		vdev->tx_fl_hwm =
610 			(uint16_t)(low_watermark + high_watermark_offset);
611 		/* Not enough free resource, stop TX OS Q */
612 		qdf_atomic_set(&vdev->os_q_paused, 1);
613 		qdf_spin_unlock_bh(&vdev->pdev->tx_mutex);
614 		return false;
615 	}
616 	qdf_spin_unlock_bh(&vdev->pdev->tx_mutex);
617 	return true;
618 }
619 
ol_txrx_ll_set_tx_pause_q_depth(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,int pause_q_depth)620 int ol_txrx_ll_set_tx_pause_q_depth(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
621 				    int pause_q_depth)
622 {
623 	struct ol_txrx_vdev_t *vdev =
624 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
625 
626 	if (!vdev) {
627 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
628 			  "%s: Invalid vdev_id %d", __func__, vdev_id);
629 		return -EINVAL;
630 	}
631 
632 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
633 	vdev->ll_pause.max_q_depth = pause_q_depth;
634 	qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
635 
636 	return 0;
637 }
638 
ol_txrx_flow_control_cb(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,bool tx_resume)639 void ol_txrx_flow_control_cb(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
640 			     bool tx_resume)
641 {
642 	struct ol_txrx_vdev_t *vdev =
643 		(struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
644 
645 	if (qdf_unlikely(!vdev)) {
646 		ol_txrx_err("vdev is NULL");
647 		return;
648 	}
649 
650 	qdf_spin_lock_bh(&vdev->flow_control_lock);
651 	if ((vdev->osif_flow_control_cb) && (vdev->osif_fc_ctx))
652 		vdev->osif_flow_control_cb(vdev->osif_fc_ctx, tx_resume);
653 	qdf_spin_unlock_bh(&vdev->flow_control_lock);
654 }
655 
656 /**
657  * ol_txrx_flow_control_is_pause() - is osif paused by flow control
658  * @vdev: vdev handle
659  *
660  * Return: true if osif is paused by flow control
661  */
ol_txrx_flow_control_is_pause(ol_txrx_vdev_handle vdev)662 static bool ol_txrx_flow_control_is_pause(ol_txrx_vdev_handle vdev)
663 {
664 	bool is_pause = false;
665 
666 	if ((vdev->osif_flow_control_is_pause) && (vdev->osif_fc_ctx))
667 		is_pause = vdev->osif_flow_control_is_pause(vdev->osif_fc_ctx);
668 
669 	return is_pause;
670 }
671 
672 /**
673  * ol_tx_flow_ct_unpause_os_q() - Unpause OS Q
674  * @pdev: physical device object
675  *
676  *
677  * Return: None
678  */
ol_tx_flow_ct_unpause_os_q(ol_txrx_pdev_handle pdev)679 void ol_tx_flow_ct_unpause_os_q(ol_txrx_pdev_handle pdev)
680 {
681 	struct ol_txrx_vdev_t *vdev;
682 	struct cdp_soc_t *soc_hdl = ol_txrx_soc_t_to_cdp_soc_t(pdev->soc);
683 
684 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
685 		if ((qdf_atomic_read(&vdev->os_q_paused) &&
686 		     (vdev->tx_fl_hwm != 0)) ||
687 		     ol_txrx_flow_control_is_pause(vdev)) {
688 			qdf_spin_lock(&pdev->tx_mutex);
689 			if (pdev->tx_desc.num_free > vdev->tx_fl_hwm) {
690 				qdf_atomic_set(&vdev->os_q_paused, 0);
691 				qdf_spin_unlock(&pdev->tx_mutex);
692 				ol_txrx_flow_control_cb(soc_hdl,
693 							vdev->vdev_id, true);
694 			} else {
695 				qdf_spin_unlock(&pdev->tx_mutex);
696 			}
697 		}
698 	}
699 }
700 
701