xref: /wlan-driver/qcacld-3.0/components/dsc/src/wlan_dsc_vdev.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-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 #include "qdf_list.h"
21*5113495bSYour Name #include "qdf_status.h"
22*5113495bSYour Name #include "qdf_talloc.h"
23*5113495bSYour Name #include "qdf_types.h"
24*5113495bSYour Name #include "__wlan_dsc.h"
25*5113495bSYour Name #include "wlan_dsc.h"
26*5113495bSYour Name #include "qdf_platform.h"
27*5113495bSYour Name 
28*5113495bSYour Name #define __dsc_driver_lock(vdev) __dsc_lock((vdev)->psoc->driver)
29*5113495bSYour Name #define __dsc_driver_unlock(vdev) __dsc_unlock((vdev)->psoc->driver)
30*5113495bSYour Name 
31*5113495bSYour Name static QDF_STATUS
__dsc_vdev_create(struct dsc_psoc * psoc,struct dsc_vdev ** out_vdev)32*5113495bSYour Name __dsc_vdev_create(struct dsc_psoc *psoc, struct dsc_vdev **out_vdev)
33*5113495bSYour Name {
34*5113495bSYour Name 	struct dsc_vdev *vdev;
35*5113495bSYour Name 
36*5113495bSYour Name 	if (!dsc_assert(psoc))
37*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
38*5113495bSYour Name 
39*5113495bSYour Name 	if (!dsc_assert(out_vdev))
40*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
41*5113495bSYour Name 
42*5113495bSYour Name 	*out_vdev = NULL;
43*5113495bSYour Name 
44*5113495bSYour Name 	vdev = qdf_talloc_type(psoc, vdev);
45*5113495bSYour Name 	if (!vdev)
46*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
47*5113495bSYour Name 
48*5113495bSYour Name 	/* init */
49*5113495bSYour Name 	vdev->psoc = psoc;
50*5113495bSYour Name 	__dsc_trans_init(&vdev->trans);
51*5113495bSYour Name 	__dsc_ops_init(&vdev->ops);
52*5113495bSYour Name 
53*5113495bSYour Name 	/* attach */
54*5113495bSYour Name 	__dsc_driver_lock(vdev);
55*5113495bSYour Name 	qdf_list_insert_back(&psoc->vdevs, &vdev->node);
56*5113495bSYour Name 	__dsc_driver_unlock(vdev);
57*5113495bSYour Name 
58*5113495bSYour Name 	*out_vdev = vdev;
59*5113495bSYour Name 
60*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
61*5113495bSYour Name }
62*5113495bSYour Name 
dsc_vdev_create(struct dsc_psoc * psoc,struct dsc_vdev ** out_vdev)63*5113495bSYour Name QDF_STATUS dsc_vdev_create(struct dsc_psoc *psoc, struct dsc_vdev **out_vdev)
64*5113495bSYour Name {
65*5113495bSYour Name 	QDF_STATUS status;
66*5113495bSYour Name 
67*5113495bSYour Name 	status =  __dsc_vdev_create(psoc, out_vdev);
68*5113495bSYour Name 
69*5113495bSYour Name 	return status;
70*5113495bSYour Name }
71*5113495bSYour Name 
__dsc_vdev_destroy(struct dsc_vdev ** out_vdev)72*5113495bSYour Name static void __dsc_vdev_destroy(struct dsc_vdev **out_vdev)
73*5113495bSYour Name {
74*5113495bSYour Name 	struct dsc_vdev *vdev;
75*5113495bSYour Name 
76*5113495bSYour Name 	if (!dsc_assert(out_vdev))
77*5113495bSYour Name 		return;
78*5113495bSYour Name 
79*5113495bSYour Name 	vdev = *out_vdev;
80*5113495bSYour Name 	if (!dsc_assert(vdev))
81*5113495bSYour Name 		return;
82*5113495bSYour Name 
83*5113495bSYour Name 	*out_vdev = NULL;
84*5113495bSYour Name 
85*5113495bSYour Name 	/* flush pending transitions */
86*5113495bSYour Name 	while (__dsc_trans_abort(&vdev->trans))
87*5113495bSYour Name 		;
88*5113495bSYour Name 
89*5113495bSYour Name 	/* detach */
90*5113495bSYour Name 	__dsc_driver_lock(vdev);
91*5113495bSYour Name 	qdf_list_remove_node(&vdev->psoc->vdevs, &vdev->node);
92*5113495bSYour Name 	__dsc_driver_unlock(vdev);
93*5113495bSYour Name 
94*5113495bSYour Name 	/* de-init */
95*5113495bSYour Name 	__dsc_ops_deinit(&vdev->ops);
96*5113495bSYour Name 	__dsc_trans_deinit(&vdev->trans);
97*5113495bSYour Name 	vdev->psoc = NULL;
98*5113495bSYour Name 
99*5113495bSYour Name 	qdf_tfree(vdev);
100*5113495bSYour Name }
101*5113495bSYour Name 
dsc_vdev_destroy(struct dsc_vdev ** out_vdev)102*5113495bSYour Name void dsc_vdev_destroy(struct dsc_vdev **out_vdev)
103*5113495bSYour Name {
104*5113495bSYour Name 	__dsc_vdev_destroy(out_vdev);
105*5113495bSYour Name }
106*5113495bSYour Name 
__dsc_vdev_wait_for_uptree_ops(struct dsc_vdev * vdev)107*5113495bSYour Name static void __dsc_vdev_wait_for_uptree_ops(struct dsc_vdev *vdev)
108*5113495bSYour Name {
109*5113495bSYour Name 	bool wait;
110*5113495bSYour Name 
111*5113495bSYour Name 	if (!dsc_assert(vdev))
112*5113495bSYour Name 		return;
113*5113495bSYour Name 
114*5113495bSYour Name 	__dsc_driver_lock(vdev);
115*5113495bSYour Name 	wait = vdev->psoc->ops.count > 0;
116*5113495bSYour Name 	if (wait)
117*5113495bSYour Name 		qdf_event_reset(&vdev->psoc->ops.event);
118*5113495bSYour Name 	__dsc_driver_unlock(vdev);
119*5113495bSYour Name 
120*5113495bSYour Name 	if (wait)
121*5113495bSYour Name 		qdf_wait_single_event(&vdev->psoc->ops.event, 0);
122*5113495bSYour Name 
123*5113495bSYour Name 	__dsc_driver_lock(vdev);
124*5113495bSYour Name 	wait = vdev->psoc->driver->ops.count > 0;
125*5113495bSYour Name 	if (wait)
126*5113495bSYour Name 		qdf_event_reset(&vdev->psoc->driver->ops.event);
127*5113495bSYour Name 	__dsc_driver_unlock(vdev);
128*5113495bSYour Name 
129*5113495bSYour Name 	if (wait)
130*5113495bSYour Name 		qdf_wait_single_event(&vdev->psoc->driver->ops.event, 0);
131*5113495bSYour Name }
132*5113495bSYour Name 
dsc_vdev_wait_for_uptree_ops(struct dsc_vdev * vdev)133*5113495bSYour Name void dsc_vdev_wait_for_uptree_ops(struct dsc_vdev *vdev)
134*5113495bSYour Name {
135*5113495bSYour Name 	__dsc_vdev_wait_for_uptree_ops(vdev);
136*5113495bSYour Name }
137*5113495bSYour Name 
138*5113495bSYour Name #define __dsc_vdev_can_op(vdev) __dsc_vdev_can_trans(vdev)
139*5113495bSYour Name 
140*5113495bSYour Name /*
141*5113495bSYour Name  * __dsc_vdev_can_trans() - Returns if the vdev transition can occur or not
142*5113495bSYour Name  * @vdev: The DSC vdev
143*5113495bSYour Name  *
144*5113495bSYour Name  * This function checks if the vdev transition can occur or not by checking if
145*5113495bSYour Name  * any other down the tree/up the tree transition/operation is taking place.
146*5113495bSYour Name  *
147*5113495bSYour Name  * If there are any driver transition taking place, then the vdev trans/ops
148*5113495bSYour Name  * should be rejected and not queued in the DSC queue. Return QDF_STATUS_E_INVAL
149*5113495bSYour Name  * in this case.
150*5113495bSYour Name  *
151*5113495bSYour Name  * If there are any psoc transition taking place because of SSR, then vdev
152*5113495bSYour Name  * trans/op should be rejected and queued in the DSC queue so that it may be
153*5113495bSYour Name  * resumed after the current trans/op is completed. return QDF_STATUS_E_BUSY
154*5113495bSYour Name  * in this case.
155*5113495bSYour Name  *
156*5113495bSYour Name  * If there is a psoc transition taking place because of psoc idle shutdown,
157*5113495bSYour Name  * then the vdev trans/ops should be rejected and queued in the DSC queue so
158*5113495bSYour Name  * that it may be resumed after the current trans/ops is completed. Return
159*5113495bSYour Name  * QDF_STATUS_E_BUSY in this case.
160*5113495bSYour Name  *
161*5113495bSYour Name  * If there are any vdev trans/ops taking place, then the vdev trans/ops
162*5113495bSYour Name  * should be rejected and queued in the DSC queue so that it may be resumed
163*5113495bSYour Name  * after the current trans/ops is completed. Return QDF_STATUS_E_BUSY in this
164*5113495bSYour Name  * case.
165*5113495bSYour Name  *
166*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if transition is allowed, error code if not.
167*5113495bSYour Name  */
__dsc_vdev_can_trans(struct dsc_vdev * vdev)168*5113495bSYour Name static QDF_STATUS __dsc_vdev_can_trans(struct dsc_vdev *vdev)
169*5113495bSYour Name {
170*5113495bSYour Name 	if (__dsc_trans_active_or_queued(&vdev->psoc->driver->trans))
171*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
172*5113495bSYour Name 
173*5113495bSYour Name 	if (qdf_is_recovering())
174*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
175*5113495bSYour Name 
176*5113495bSYour Name 	if (__dsc_trans_active_or_queued(&vdev->psoc->trans)) {
177*5113495bSYour Name 		/* psoc idle shutdown(wifi off) needs to be added in DSC queue
178*5113495bSYour Name 		 * to avoid wifi on failure while previous psoc idle shutdown
179*5113495bSYour Name 		 * is in progress and wifi is turned on. And Wifi On also needs
180*5113495bSYour Name 		 * to be added to the queue so that it waits for SSR to
181*5113495bSYour Name 		 * complete.
182*5113495bSYour Name 		 */
183*5113495bSYour Name 		if (qdf_is_driver_unloading())
184*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
185*5113495bSYour Name 		else
186*5113495bSYour Name 			return QDF_STATUS_E_BUSY;
187*5113495bSYour Name 	}
188*5113495bSYour Name 
189*5113495bSYour Name 	if (__dsc_trans_active_or_queued(&vdev->trans))
190*5113495bSYour Name 		return QDF_STATUS_E_BUSY;
191*5113495bSYour Name 
192*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
193*5113495bSYour Name }
194*5113495bSYour Name 
195*5113495bSYour Name static QDF_STATUS
__dsc_vdev_trans_start_nolock(struct dsc_vdev * vdev,const char * desc)196*5113495bSYour Name __dsc_vdev_trans_start_nolock(struct dsc_vdev *vdev, const char *desc)
197*5113495bSYour Name {
198*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
199*5113495bSYour Name 
200*5113495bSYour Name 	status = __dsc_vdev_can_trans(vdev);
201*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
202*5113495bSYour Name 		return status;
203*5113495bSYour Name 
204*5113495bSYour Name 	return __dsc_trans_start(&vdev->trans, desc);
205*5113495bSYour Name }
206*5113495bSYour Name 
207*5113495bSYour Name static QDF_STATUS
__dsc_vdev_trans_start(struct dsc_vdev * vdev,const char * desc)208*5113495bSYour Name __dsc_vdev_trans_start(struct dsc_vdev *vdev, const char *desc)
209*5113495bSYour Name {
210*5113495bSYour Name 	QDF_STATUS status;
211*5113495bSYour Name 
212*5113495bSYour Name 	if (!dsc_assert(vdev))
213*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
214*5113495bSYour Name 
215*5113495bSYour Name 	if (!dsc_assert(desc))
216*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
217*5113495bSYour Name 
218*5113495bSYour Name 	__dsc_driver_lock(vdev);
219*5113495bSYour Name 	status = __dsc_vdev_trans_start_nolock(vdev, desc);
220*5113495bSYour Name 	__dsc_driver_unlock(vdev);
221*5113495bSYour Name 
222*5113495bSYour Name 	return status;
223*5113495bSYour Name }
224*5113495bSYour Name 
dsc_vdev_trans_start(struct dsc_vdev * vdev,const char * desc)225*5113495bSYour Name QDF_STATUS dsc_vdev_trans_start(struct dsc_vdev *vdev, const char *desc)
226*5113495bSYour Name {
227*5113495bSYour Name 	QDF_STATUS status;
228*5113495bSYour Name 
229*5113495bSYour Name 	dsc_enter_str(desc);
230*5113495bSYour Name 	status = __dsc_vdev_trans_start(vdev, desc);
231*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
232*5113495bSYour Name 		dsc_exit_status(status);
233*5113495bSYour Name 
234*5113495bSYour Name 	return status;
235*5113495bSYour Name }
236*5113495bSYour Name 
237*5113495bSYour Name static QDF_STATUS
__dsc_vdev_trans_start_wait(struct dsc_vdev * vdev,const char * desc)238*5113495bSYour Name __dsc_vdev_trans_start_wait(struct dsc_vdev *vdev, const char *desc)
239*5113495bSYour Name {
240*5113495bSYour Name 	QDF_STATUS status;
241*5113495bSYour Name 	struct dsc_tran tran = { 0 };
242*5113495bSYour Name 
243*5113495bSYour Name 	if (!dsc_assert(vdev))
244*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
245*5113495bSYour Name 
246*5113495bSYour Name 	if (!dsc_assert(desc))
247*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
248*5113495bSYour Name 
249*5113495bSYour Name 	__dsc_driver_lock(vdev);
250*5113495bSYour Name 
251*5113495bSYour Name 	/* try to start without waiting */
252*5113495bSYour Name 	status = __dsc_vdev_trans_start_nolock(vdev, desc);
253*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status) || status == QDF_STATUS_E_INVAL)
254*5113495bSYour Name 		goto unlock;
255*5113495bSYour Name 
256*5113495bSYour Name 	status = __dsc_trans_queue(&vdev->trans, &tran, desc);
257*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
258*5113495bSYour Name 		goto unlock;
259*5113495bSYour Name 
260*5113495bSYour Name 	__dsc_driver_unlock(vdev);
261*5113495bSYour Name 
262*5113495bSYour Name 	return __dsc_tran_wait(&tran);
263*5113495bSYour Name 
264*5113495bSYour Name unlock:
265*5113495bSYour Name 	__dsc_driver_unlock(vdev);
266*5113495bSYour Name 
267*5113495bSYour Name 	return status;
268*5113495bSYour Name }
269*5113495bSYour Name 
dsc_vdev_trans_start_wait(struct dsc_vdev * vdev,const char * desc)270*5113495bSYour Name QDF_STATUS dsc_vdev_trans_start_wait(struct dsc_vdev *vdev, const char *desc)
271*5113495bSYour Name {
272*5113495bSYour Name 	QDF_STATUS status;
273*5113495bSYour Name 
274*5113495bSYour Name 	dsc_enter_str(desc);
275*5113495bSYour Name 	status = __dsc_vdev_trans_start_wait(vdev, desc);
276*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
277*5113495bSYour Name 		dsc_exit_status(status);
278*5113495bSYour Name 
279*5113495bSYour Name 	return status;
280*5113495bSYour Name }
281*5113495bSYour Name 
__dsc_vdev_trigger_trans(struct dsc_vdev * vdev)282*5113495bSYour Name static void __dsc_vdev_trigger_trans(struct dsc_vdev *vdev)
283*5113495bSYour Name {
284*5113495bSYour Name 	if (__dsc_driver_trans_trigger_checked(vdev->psoc->driver))
285*5113495bSYour Name 		return;
286*5113495bSYour Name 
287*5113495bSYour Name 	if (__dsc_psoc_trans_trigger_checked(vdev->psoc))
288*5113495bSYour Name 		return;
289*5113495bSYour Name 
290*5113495bSYour Name 	__dsc_trans_trigger(&vdev->trans);
291*5113495bSYour Name }
292*5113495bSYour Name 
__dsc_vdev_trans_stop(struct dsc_vdev * vdev)293*5113495bSYour Name static void __dsc_vdev_trans_stop(struct dsc_vdev *vdev)
294*5113495bSYour Name {
295*5113495bSYour Name 	if (!dsc_assert(vdev))
296*5113495bSYour Name 		return;
297*5113495bSYour Name 
298*5113495bSYour Name 	__dsc_driver_lock(vdev);
299*5113495bSYour Name 
300*5113495bSYour Name 	__dsc_trans_stop(&vdev->trans);
301*5113495bSYour Name 	__dsc_vdev_trigger_trans(vdev);
302*5113495bSYour Name 
303*5113495bSYour Name 	__dsc_driver_unlock(vdev);
304*5113495bSYour Name }
305*5113495bSYour Name 
dsc_vdev_trans_stop(struct dsc_vdev * vdev)306*5113495bSYour Name void dsc_vdev_trans_stop(struct dsc_vdev *vdev)
307*5113495bSYour Name {
308*5113495bSYour Name 	__dsc_vdev_trans_stop(vdev);
309*5113495bSYour Name }
310*5113495bSYour Name 
__dsc_vdev_assert_trans_protected(struct dsc_vdev * vdev)311*5113495bSYour Name static void __dsc_vdev_assert_trans_protected(struct dsc_vdev *vdev)
312*5113495bSYour Name {
313*5113495bSYour Name 	if (!dsc_assert(vdev))
314*5113495bSYour Name 		return;
315*5113495bSYour Name 
316*5113495bSYour Name 	__dsc_driver_lock(vdev);
317*5113495bSYour Name 	dsc_assert(__dsc_trans_active(&vdev->trans) ||
318*5113495bSYour Name 		   __dsc_trans_active(&vdev->psoc->trans) ||
319*5113495bSYour Name 		   __dsc_trans_active(&vdev->psoc->driver->trans));
320*5113495bSYour Name 	__dsc_driver_unlock(vdev);
321*5113495bSYour Name }
322*5113495bSYour Name 
dsc_vdev_assert_trans_protected(struct dsc_vdev * vdev)323*5113495bSYour Name void dsc_vdev_assert_trans_protected(struct dsc_vdev *vdev)
324*5113495bSYour Name {
325*5113495bSYour Name 	__dsc_vdev_assert_trans_protected(vdev);
326*5113495bSYour Name }
327*5113495bSYour Name 
__dsc_vdev_op_start(struct dsc_vdev * vdev,const char * func)328*5113495bSYour Name static QDF_STATUS __dsc_vdev_op_start(struct dsc_vdev *vdev, const char *func)
329*5113495bSYour Name {
330*5113495bSYour Name 	QDF_STATUS status;
331*5113495bSYour Name 
332*5113495bSYour Name 	if (!dsc_assert(vdev))
333*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
334*5113495bSYour Name 
335*5113495bSYour Name 	if (!dsc_assert(func))
336*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
337*5113495bSYour Name 
338*5113495bSYour Name 	__dsc_driver_lock(vdev);
339*5113495bSYour Name 
340*5113495bSYour Name 	status = __dsc_vdev_can_op(vdev);
341*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
342*5113495bSYour Name 		goto unlock;
343*5113495bSYour Name 
344*5113495bSYour Name 	status = __dsc_ops_insert(&vdev->ops, func);
345*5113495bSYour Name 
346*5113495bSYour Name unlock:
347*5113495bSYour Name 	__dsc_driver_unlock(vdev);
348*5113495bSYour Name 
349*5113495bSYour Name 	return status;
350*5113495bSYour Name }
351*5113495bSYour Name 
_dsc_vdev_op_start(struct dsc_vdev * vdev,const char * func)352*5113495bSYour Name QDF_STATUS _dsc_vdev_op_start(struct dsc_vdev *vdev, const char *func)
353*5113495bSYour Name {
354*5113495bSYour Name 	QDF_STATUS status;
355*5113495bSYour Name 
356*5113495bSYour Name 	/* do not log from here because it can flood log message because vdev
357*5113495bSYour Name 	 * op protect is per vdev operation
358*5113495bSYour Name 	 */
359*5113495bSYour Name 
360*5113495bSYour Name 	status = __dsc_vdev_op_start(vdev, func);
361*5113495bSYour Name 
362*5113495bSYour Name 	return status;
363*5113495bSYour Name }
364*5113495bSYour Name 
__dsc_vdev_op_stop(struct dsc_vdev * vdev,const char * func)365*5113495bSYour Name static void __dsc_vdev_op_stop(struct dsc_vdev *vdev, const char *func)
366*5113495bSYour Name {
367*5113495bSYour Name 	if (!dsc_assert(vdev))
368*5113495bSYour Name 		return;
369*5113495bSYour Name 
370*5113495bSYour Name 	if (!dsc_assert(func))
371*5113495bSYour Name 		return;
372*5113495bSYour Name 
373*5113495bSYour Name 	__dsc_driver_lock(vdev);
374*5113495bSYour Name 	if (__dsc_ops_remove(&vdev->ops, func))
375*5113495bSYour Name 		qdf_event_set(&vdev->ops.event);
376*5113495bSYour Name 	__dsc_driver_unlock(vdev);
377*5113495bSYour Name }
378*5113495bSYour Name 
_dsc_vdev_op_stop(struct dsc_vdev * vdev,const char * func)379*5113495bSYour Name void _dsc_vdev_op_stop(struct dsc_vdev *vdev, const char *func)
380*5113495bSYour Name {
381*5113495bSYour Name 	/* do not log from here because it can flood log message because vdev
382*5113495bSYour Name 	 * op protect is per vdev operation
383*5113495bSYour Name 	 */
384*5113495bSYour Name 	__dsc_vdev_op_stop(vdev, func);
385*5113495bSYour Name }
386*5113495bSYour Name 
__dsc_vdev_wait_for_ops(struct dsc_vdev * vdev)387*5113495bSYour Name static void __dsc_vdev_wait_for_ops(struct dsc_vdev *vdev)
388*5113495bSYour Name {
389*5113495bSYour Name 	bool wait;
390*5113495bSYour Name 
391*5113495bSYour Name 	if (!dsc_assert(vdev))
392*5113495bSYour Name 		return;
393*5113495bSYour Name 
394*5113495bSYour Name 	__dsc_driver_lock(vdev);
395*5113495bSYour Name 
396*5113495bSYour Name 	wait = vdev->ops.count > 0;
397*5113495bSYour Name 	if (wait)
398*5113495bSYour Name 		qdf_event_reset(&vdev->ops.event);
399*5113495bSYour Name 
400*5113495bSYour Name 	__dsc_driver_unlock(vdev);
401*5113495bSYour Name 
402*5113495bSYour Name 	if (wait)
403*5113495bSYour Name 		qdf_wait_single_event(&vdev->ops.event, 0);
404*5113495bSYour Name }
405*5113495bSYour Name 
dsc_vdev_wait_for_ops(struct dsc_vdev * vdev)406*5113495bSYour Name void dsc_vdev_wait_for_ops(struct dsc_vdev *vdev)
407*5113495bSYour Name {
408*5113495bSYour Name 	__dsc_vdev_wait_for_ops(vdev);
409*5113495bSYour Name }
410*5113495bSYour Name 
dsc_vdev_get_cached_cmd(struct dsc_vdev * vdev)411*5113495bSYour Name uint8_t dsc_vdev_get_cached_cmd(struct dsc_vdev *vdev)
412*5113495bSYour Name {
413*5113495bSYour Name 	return vdev->nb_cmd_during_ssr;
414*5113495bSYour Name }
415*5113495bSYour Name 
dsc_vdev_cache_command(struct dsc_vdev * vdev,uint8_t cmd_id)416*5113495bSYour Name void dsc_vdev_cache_command(struct dsc_vdev *vdev, uint8_t cmd_id)
417*5113495bSYour Name {
418*5113495bSYour Name 	vdev->nb_cmd_during_ssr = cmd_id;
419*5113495bSYour Name }
420*5113495bSYour Name 
421