xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_tx_throttle.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /*
21*5113495bSYour Name  * This file was originally distributed by Qualcomm Atheros, Inc.
22*5113495bSYour Name  * under proprietary terms before Copyright ownership was assigned
23*5113495bSYour Name  * to the Linux Foundation.
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include <qdf_nbuf.h>           /* qdf_nbuf_t, etc. */
27*5113495bSYour Name #include <qdf_atomic.h>         /* qdf_atomic_read, etc. */
28*5113495bSYour Name #include <ol_cfg.h>             /* ol_cfg_addba_retry */
29*5113495bSYour Name #include <htt.h>                /* HTT_TX_EXT_TID_MGMT */
30*5113495bSYour Name #include <ol_htt_tx_api.h>      /* htt_tx_desc_tid */
31*5113495bSYour Name #include <ol_txrx_api.h>        /* ol_txrx_vdev_handle */
32*5113495bSYour Name #include <ol_txrx_ctrl_api.h>   /* ol_txrx_sync, ol_tx_addba_conf */
33*5113495bSYour Name #include <cdp_txrx_tx_throttle.h>
34*5113495bSYour Name #include <ol_ctrl_txrx_api.h>   /* ol_ctrl_addba_req */
35*5113495bSYour Name #include <ol_txrx_internal.h>   /* TXRX_ASSERT1, etc. */
36*5113495bSYour Name #include <ol_tx_desc.h>         /* ol_tx_desc, ol_tx_desc_frame_list_free */
37*5113495bSYour Name #include <ol_tx.h>              /* ol_tx_vdev_ll_pause_queue_send */
38*5113495bSYour Name #include <ol_tx_sched.h>	/* ol_tx_sched_notify, etc. */
39*5113495bSYour Name #include <ol_tx_queue.h>
40*5113495bSYour Name #include <ol_txrx.h>          /* ol_tx_desc_pool_size_hl */
41*5113495bSYour Name #include <ol_txrx_dbg.h>        /* ENABLE_TX_QUEUE_LOG */
42*5113495bSYour Name #include <qdf_types.h>          /* bool */
43*5113495bSYour Name #include "cdp_txrx_flow_ctrl_legacy.h"
44*5113495bSYour Name #include <ol_txrx_peer_find.h>
45*5113495bSYour Name #include <cdp_txrx_handle.h>
46*5113495bSYour Name 
47*5113495bSYour Name #ifdef QCA_LL_TX_FLOW_CONTROL_V2
48*5113495bSYour Name /**
49*5113495bSYour Name  * ol_txrx_thermal_pause() - pause due to thermal mitigation
50*5113495bSYour Name  * @pdev: pdev handle
51*5113495bSYour Name  *
52*5113495bSYour Name  * Return: none
53*5113495bSYour Name  */
54*5113495bSYour Name static inline
ol_txrx_thermal_pause(struct ol_txrx_pdev_t * pdev)55*5113495bSYour Name void ol_txrx_thermal_pause(struct ol_txrx_pdev_t *pdev)
56*5113495bSYour Name {
57*5113495bSYour Name 	ol_txrx_pdev_pause(pdev, OL_TXQ_PAUSE_REASON_THERMAL_MITIGATION);
58*5113495bSYour Name }
59*5113495bSYour Name 
60*5113495bSYour Name /**
61*5113495bSYour Name  * ol_txrx_thermal_unpause() - unpause due to thermal mitigation
62*5113495bSYour Name  * @pdev: pdev handle
63*5113495bSYour Name  *
64*5113495bSYour Name  * Return: none
65*5113495bSYour Name  */
66*5113495bSYour Name static inline
ol_txrx_thermal_unpause(struct ol_txrx_pdev_t * pdev)67*5113495bSYour Name void ol_txrx_thermal_unpause(struct ol_txrx_pdev_t *pdev)
68*5113495bSYour Name {
69*5113495bSYour Name 	ol_txrx_pdev_unpause(pdev, OL_TXQ_PAUSE_REASON_THERMAL_MITIGATION);
70*5113495bSYour Name }
71*5113495bSYour Name #else
72*5113495bSYour Name /**
73*5113495bSYour Name  * ol_txrx_thermal_pause() - pause due to thermal mitigation
74*5113495bSYour Name  * @pdev: pdev handle
75*5113495bSYour Name  *
76*5113495bSYour Name  * Return: none
77*5113495bSYour Name  */
78*5113495bSYour Name static inline
ol_txrx_thermal_pause(struct ol_txrx_pdev_t * pdev)79*5113495bSYour Name void ol_txrx_thermal_pause(struct ol_txrx_pdev_t *pdev)
80*5113495bSYour Name {
81*5113495bSYour Name }
82*5113495bSYour Name 
83*5113495bSYour Name /**
84*5113495bSYour Name  * ol_txrx_thermal_unpause() - unpause due to thermal mitigation
85*5113495bSYour Name  * @pdev: pdev handle
86*5113495bSYour Name  *
87*5113495bSYour Name  * Return: none
88*5113495bSYour Name  */
89*5113495bSYour Name static inline
ol_txrx_thermal_unpause(struct ol_txrx_pdev_t * pdev)90*5113495bSYour Name void ol_txrx_thermal_unpause(struct ol_txrx_pdev_t *pdev)
91*5113495bSYour Name {
92*5113495bSYour Name 	ol_tx_pdev_ll_pause_queue_send_all(pdev);
93*5113495bSYour Name }
94*5113495bSYour Name #endif
95*5113495bSYour Name 
ol_tx_pdev_throttle_phase_timer(void * context)96*5113495bSYour Name static void ol_tx_pdev_throttle_phase_timer(void *context)
97*5113495bSYour Name {
98*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context;
99*5113495bSYour Name 	int ms;
100*5113495bSYour Name 	enum throttle_level cur_level;
101*5113495bSYour Name 	enum throttle_phase cur_phase;
102*5113495bSYour Name 
103*5113495bSYour Name 	/* update the phase */
104*5113495bSYour Name 	pdev->tx_throttle.current_throttle_phase++;
105*5113495bSYour Name 
106*5113495bSYour Name 	if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_MAX)
107*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
108*5113495bSYour Name 
109*5113495bSYour Name 	if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF) {
110*5113495bSYour Name 		/* Traffic is stopped */
111*5113495bSYour Name 		ol_txrx_dbg(
112*5113495bSYour Name 				   "throttle phase --> OFF");
113*5113495bSYour Name 		ol_txrx_throttle_pause(pdev);
114*5113495bSYour Name 		ol_txrx_thermal_pause(pdev);
115*5113495bSYour Name 		pdev->tx_throttle.prev_outstanding_num = 0;
116*5113495bSYour Name 		cur_level = pdev->tx_throttle.current_throttle_level;
117*5113495bSYour Name 		cur_phase = pdev->tx_throttle.current_throttle_phase;
118*5113495bSYour Name 		ms = pdev->tx_throttle.throttle_time_ms[cur_level][cur_phase];
119*5113495bSYour Name 		if (pdev->tx_throttle.current_throttle_level !=
120*5113495bSYour Name 				THROTTLE_LEVEL_0) {
121*5113495bSYour Name 			ol_txrx_dbg(
122*5113495bSYour Name 					   "start timer %d ms", ms);
123*5113495bSYour Name 			qdf_timer_start(&pdev->tx_throttle.
124*5113495bSYour Name 							phase_timer, ms);
125*5113495bSYour Name 		}
126*5113495bSYour Name 	} else {
127*5113495bSYour Name 		/* Traffic can go */
128*5113495bSYour Name 		ol_txrx_dbg(
129*5113495bSYour Name 					"throttle phase --> ON");
130*5113495bSYour Name 		ol_txrx_throttle_unpause(pdev);
131*5113495bSYour Name 		ol_txrx_thermal_unpause(pdev);
132*5113495bSYour Name 		cur_level = pdev->tx_throttle.current_throttle_level;
133*5113495bSYour Name 		cur_phase = pdev->tx_throttle.current_throttle_phase;
134*5113495bSYour Name 		ms = pdev->tx_throttle.throttle_time_ms[cur_level][cur_phase];
135*5113495bSYour Name 		if (pdev->tx_throttle.current_throttle_level !=
136*5113495bSYour Name 		    THROTTLE_LEVEL_0) {
137*5113495bSYour Name 			ol_txrx_dbg("start timer %d ms", ms);
138*5113495bSYour Name 			qdf_timer_start(&pdev->tx_throttle.phase_timer,	ms);
139*5113495bSYour Name 		}
140*5113495bSYour Name 	}
141*5113495bSYour Name }
142*5113495bSYour Name 
143*5113495bSYour Name #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
ol_tx_pdev_throttle_tx_timer(void * context)144*5113495bSYour Name static void ol_tx_pdev_throttle_tx_timer(void *context)
145*5113495bSYour Name {
146*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context;
147*5113495bSYour Name 
148*5113495bSYour Name 	ol_tx_pdev_ll_pause_queue_send_all(pdev);
149*5113495bSYour Name }
150*5113495bSYour Name #endif
151*5113495bSYour Name 
152*5113495bSYour Name #ifdef CONFIG_HL_SUPPORT
153*5113495bSYour Name 
154*5113495bSYour Name /**
155*5113495bSYour Name  * ol_tx_set_throttle_phase_time() - Set the thermal mitgation throttle phase
156*5113495bSYour Name  *				     and time
157*5113495bSYour Name  * @pdev: the peer device object
158*5113495bSYour Name  * @level: throttle phase level
159*5113495bSYour Name  * @ms: throttle time
160*5113495bSYour Name  *
161*5113495bSYour Name  * Return: None
162*5113495bSYour Name  */
163*5113495bSYour Name static void
ol_tx_set_throttle_phase_time(struct ol_txrx_pdev_t * pdev,int level,int * ms)164*5113495bSYour Name ol_tx_set_throttle_phase_time(struct ol_txrx_pdev_t *pdev, int level, int *ms)
165*5113495bSYour Name {
166*5113495bSYour Name 	qdf_timer_stop(&pdev->tx_throttle.phase_timer);
167*5113495bSYour Name 
168*5113495bSYour Name 	/* Set the phase */
169*5113495bSYour Name 	if (level != THROTTLE_LEVEL_0) {
170*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
171*5113495bSYour Name 		*ms = pdev->tx_throttle.throttle_time_ms[level]
172*5113495bSYour Name 						[THROTTLE_PHASE_OFF];
173*5113495bSYour Name 
174*5113495bSYour Name 		/* pause all */
175*5113495bSYour Name 		ol_txrx_throttle_pause(pdev);
176*5113495bSYour Name 	} else {
177*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_ON;
178*5113495bSYour Name 		*ms = pdev->tx_throttle.throttle_time_ms[level]
179*5113495bSYour Name 						[THROTTLE_PHASE_ON];
180*5113495bSYour Name 
181*5113495bSYour Name 		/* unpause all */
182*5113495bSYour Name 		ol_txrx_throttle_unpause(pdev);
183*5113495bSYour Name 	}
184*5113495bSYour Name }
185*5113495bSYour Name #else
186*5113495bSYour Name 
187*5113495bSYour Name static void
ol_tx_set_throttle_phase_time(struct ol_txrx_pdev_t * pdev,int level,int * ms)188*5113495bSYour Name ol_tx_set_throttle_phase_time(struct ol_txrx_pdev_t *pdev, int level, int *ms)
189*5113495bSYour Name {
190*5113495bSYour Name 	int phase_on_time, phase_off_time;
191*5113495bSYour Name 
192*5113495bSYour Name 	qdf_timer_stop(&pdev->tx_throttle.phase_timer);
193*5113495bSYour Name 
194*5113495bSYour Name 	phase_on_time =
195*5113495bSYour Name 		pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_ON];
196*5113495bSYour Name 	phase_off_time =
197*5113495bSYour Name 		pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_OFF];
198*5113495bSYour Name 	if (phase_on_time && phase_off_time) {
199*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
200*5113495bSYour Name 		*ms =
201*5113495bSYour Name 		pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_OFF];
202*5113495bSYour Name 		ol_txrx_throttle_pause(pdev);
203*5113495bSYour Name 		ol_txrx_thermal_pause(pdev);
204*5113495bSYour Name 	} else if (!phase_off_time) {
205*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
206*5113495bSYour Name 		*ms = 0;
207*5113495bSYour Name 		ol_txrx_throttle_unpause(pdev);
208*5113495bSYour Name 		ol_txrx_thermal_unpause(pdev);
209*5113495bSYour Name 	} else {
210*5113495bSYour Name 		pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
211*5113495bSYour Name 		*ms = 0;
212*5113495bSYour Name 		ol_txrx_throttle_pause(pdev);
213*5113495bSYour Name 		ol_txrx_thermal_pause(pdev);
214*5113495bSYour Name 	}
215*5113495bSYour Name }
216*5113495bSYour Name #endif
217*5113495bSYour Name 
ol_tx_throttle_set_level(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,int level)218*5113495bSYour Name void ol_tx_throttle_set_level(struct cdp_soc_t *soc_hdl,
219*5113495bSYour Name 			      uint8_t pdev_id, int level)
220*5113495bSYour Name {
221*5113495bSYour Name 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
222*5113495bSYour Name 	ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
223*5113495bSYour Name 	int ms = 0;
224*5113495bSYour Name 
225*5113495bSYour Name 	if (level >= THROTTLE_LEVEL_MAX) {
226*5113495bSYour Name 		ol_txrx_dbg("invalid throttle level set %d, ignoring", level);
227*5113495bSYour Name 		return;
228*5113495bSYour Name 	}
229*5113495bSYour Name 
230*5113495bSYour Name 	if (qdf_unlikely(!pdev)) {
231*5113495bSYour Name 		ol_txrx_err("pdev is NULL");
232*5113495bSYour Name 		return;
233*5113495bSYour Name 	}
234*5113495bSYour Name 
235*5113495bSYour Name 	ol_txrx_info("Setting throttle level %d", level);
236*5113495bSYour Name 
237*5113495bSYour Name 	/* Set the current throttle level */
238*5113495bSYour Name 	pdev->tx_throttle.current_throttle_level = (enum throttle_level)level;
239*5113495bSYour Name 	pdev->tx_throttle.prev_outstanding_num = 0;
240*5113495bSYour Name 
241*5113495bSYour Name 	ol_tx_set_throttle_phase_time(pdev, level, &ms);
242*5113495bSYour Name 
243*5113495bSYour Name 	if (ms)
244*5113495bSYour Name 		qdf_timer_start(&pdev->tx_throttle.phase_timer, ms);
245*5113495bSYour Name }
246*5113495bSYour Name 
ol_tx_throttle_init_period(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,int period,uint8_t * dutycycle_level)247*5113495bSYour Name void ol_tx_throttle_init_period(struct cdp_soc_t *soc_hdl,
248*5113495bSYour Name 				uint8_t pdev_id, int period,
249*5113495bSYour Name 				uint8_t *dutycycle_level)
250*5113495bSYour Name {
251*5113495bSYour Name 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
252*5113495bSYour Name 	ol_txrx_pdev_handle pdev;
253*5113495bSYour Name 	int i;
254*5113495bSYour Name 
255*5113495bSYour Name 	if (qdf_unlikely(!soc)) {
256*5113495bSYour Name 		ol_txrx_err("soc is NULL");
257*5113495bSYour Name 		return;
258*5113495bSYour Name 	}
259*5113495bSYour Name 
260*5113495bSYour Name 	pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
261*5113495bSYour Name 	if (qdf_unlikely(!pdev)) {
262*5113495bSYour Name 		ol_txrx_err("pdev is NULL");
263*5113495bSYour Name 		return;
264*5113495bSYour Name 	}
265*5113495bSYour Name 
266*5113495bSYour Name 	/* Set the current throttle level */
267*5113495bSYour Name 	pdev->tx_throttle.throttle_period_ms = period;
268*5113495bSYour Name 
269*5113495bSYour Name 	ol_txrx_dbg("level  OFF  ON");
270*5113495bSYour Name 	for (i = 0; i < THROTTLE_LEVEL_MAX; i++) {
271*5113495bSYour Name 		pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_ON] =
272*5113495bSYour Name 			pdev->tx_throttle.throttle_period_ms -
273*5113495bSYour Name 				((dutycycle_level[i] *
274*5113495bSYour Name 				  pdev->tx_throttle.throttle_period_ms) / 100);
275*5113495bSYour Name 		pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_OFF] =
276*5113495bSYour Name 			pdev->tx_throttle.throttle_period_ms -
277*5113495bSYour Name 			pdev->tx_throttle.throttle_time_ms[
278*5113495bSYour Name 				i][THROTTLE_PHASE_ON];
279*5113495bSYour Name 		ol_txrx_dbg("%d      %d    %d", i,
280*5113495bSYour Name 			    pdev->tx_throttle.
281*5113495bSYour Name 			    throttle_time_ms[i][THROTTLE_PHASE_OFF],
282*5113495bSYour Name 			    pdev->tx_throttle.
283*5113495bSYour Name 			    throttle_time_ms[i][THROTTLE_PHASE_ON]);
284*5113495bSYour Name 	}
285*5113495bSYour Name }
286*5113495bSYour Name 
ol_tx_throttle_init(struct ol_txrx_pdev_t * pdev)287*5113495bSYour Name void ol_tx_throttle_init(struct ol_txrx_pdev_t *pdev)
288*5113495bSYour Name {
289*5113495bSYour Name 	uint32_t throttle_period;
290*5113495bSYour Name 	uint8_t dutycycle_level[THROTTLE_LEVEL_MAX];
291*5113495bSYour Name 	int i;
292*5113495bSYour Name 
293*5113495bSYour Name 	pdev->tx_throttle.current_throttle_level = THROTTLE_LEVEL_0;
294*5113495bSYour Name 	pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF;
295*5113495bSYour Name 	qdf_spinlock_create(&pdev->tx_throttle.mutex);
296*5113495bSYour Name 
297*5113495bSYour Name 	throttle_period = ol_cfg_throttle_period_ms(pdev->ctrl_pdev);
298*5113495bSYour Name 
299*5113495bSYour Name 	for (i = 0; i < THROTTLE_LEVEL_MAX; i++)
300*5113495bSYour Name 		dutycycle_level[i] =
301*5113495bSYour Name 			ol_cfg_throttle_duty_cycle_level(pdev->ctrl_pdev, i);
302*5113495bSYour Name 
303*5113495bSYour Name 	ol_tx_throttle_init_period(cds_get_context(QDF_MODULE_ID_SOC), pdev->id,
304*5113495bSYour Name 				   throttle_period, &dutycycle_level[0]);
305*5113495bSYour Name 
306*5113495bSYour Name 	qdf_timer_init(pdev->osdev, &pdev->tx_throttle.phase_timer,
307*5113495bSYour Name 		       ol_tx_pdev_throttle_phase_timer, pdev,
308*5113495bSYour Name 		       QDF_TIMER_TYPE_SW);
309*5113495bSYour Name 
310*5113495bSYour Name #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
311*5113495bSYour Name 	qdf_timer_init(pdev->osdev, &pdev->tx_throttle.tx_timer,
312*5113495bSYour Name 		       ol_tx_pdev_throttle_tx_timer, pdev, QDF_TIMER_TYPE_SW);
313*5113495bSYour Name #endif
314*5113495bSYour Name 
315*5113495bSYour Name 	pdev->tx_throttle.tx_threshold = THROTTLE_TX_THRESHOLD;
316*5113495bSYour Name }
317*5113495bSYour Name 
318*5113495bSYour Name void
ol_txrx_throttle_pause(ol_txrx_pdev_handle pdev)319*5113495bSYour Name ol_txrx_throttle_pause(ol_txrx_pdev_handle pdev)
320*5113495bSYour Name {
321*5113495bSYour Name 	qdf_spin_lock_bh(&pdev->tx_throttle.mutex);
322*5113495bSYour Name 
323*5113495bSYour Name 	if (pdev->tx_throttle.is_paused) {
324*5113495bSYour Name 		qdf_spin_unlock_bh(&pdev->tx_throttle.mutex);
325*5113495bSYour Name 		return;
326*5113495bSYour Name 	}
327*5113495bSYour Name 
328*5113495bSYour Name 	pdev->tx_throttle.is_paused = true;
329*5113495bSYour Name 	qdf_spin_unlock_bh(&pdev->tx_throttle.mutex);
330*5113495bSYour Name 	ol_txrx_pdev_pause(pdev, 0);
331*5113495bSYour Name }
332*5113495bSYour Name 
333*5113495bSYour Name void
ol_txrx_throttle_unpause(ol_txrx_pdev_handle pdev)334*5113495bSYour Name ol_txrx_throttle_unpause(ol_txrx_pdev_handle pdev)
335*5113495bSYour Name {
336*5113495bSYour Name 	qdf_spin_lock_bh(&pdev->tx_throttle.mutex);
337*5113495bSYour Name 
338*5113495bSYour Name 	if (!pdev->tx_throttle.is_paused) {
339*5113495bSYour Name 		qdf_spin_unlock_bh(&pdev->tx_throttle.mutex);
340*5113495bSYour Name 		return;
341*5113495bSYour Name 	}
342*5113495bSYour Name 
343*5113495bSYour Name 	pdev->tx_throttle.is_paused = false;
344*5113495bSYour Name 	qdf_spin_unlock_bh(&pdev->tx_throttle.mutex);
345*5113495bSYour Name 	ol_txrx_pdev_unpause(pdev, 0);
346*5113495bSYour Name }
347