xref: /wlan-driver/qcacld-3.0/os_if/sync/src/osif_driver_sync.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2019, 2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name  * above copyright notice and this permission notice appear in all
7*5113495bSYour Name  * copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name 
19*5113495bSYour Name #include "__osif_driver_sync.h"
20*5113495bSYour Name #include "osif_driver_sync.h"
21*5113495bSYour Name #include "qdf_lock.h"
22*5113495bSYour Name #include "qdf_status.h"
23*5113495bSYour Name #include "qdf_types.h"
24*5113495bSYour Name #include "wlan_dsc_driver.h"
25*5113495bSYour Name #include "wlan_dsc_psoc.h"
26*5113495bSYour Name 
27*5113495bSYour Name /**
28*5113495bSYour Name  * struct osif_driver_sync - a driver synchronization context
29*5113495bSYour Name  * @dsc_driver: the dsc_driver used for synchronization
30*5113495bSYour Name  * @in_use: indicates if the context is being used
31*5113495bSYour Name  * @is_registered: indicates if the context is registered for
32*5113495bSYour Name  *	transitions/operations
33*5113495bSYour Name  */
34*5113495bSYour Name struct osif_driver_sync {
35*5113495bSYour Name 	struct dsc_driver *dsc_driver;
36*5113495bSYour Name 	bool in_use;
37*5113495bSYour Name 	bool is_registered;
38*5113495bSYour Name };
39*5113495bSYour Name 
40*5113495bSYour Name static struct osif_driver_sync __osif_driver_sync;
41*5113495bSYour Name static qdf_spinlock_t __osif_driver_sync_lock;
42*5113495bSYour Name 
43*5113495bSYour Name #define osif_driver_sync_lock_create() \
44*5113495bSYour Name 	qdf_spinlock_create(&__osif_driver_sync_lock)
45*5113495bSYour Name #define osif_driver_sync_lock_destroy() \
46*5113495bSYour Name 	qdf_spinlock_destroy(&__osif_driver_sync_lock)
47*5113495bSYour Name #define osif_driver_sync_lock() qdf_spin_lock_bh(&__osif_driver_sync_lock)
48*5113495bSYour Name #define osif_driver_sync_unlock() qdf_spin_unlock_bh(&__osif_driver_sync_lock)
49*5113495bSYour Name 
osif_driver_sync_lookup(void)50*5113495bSYour Name static struct osif_driver_sync *osif_driver_sync_lookup(void)
51*5113495bSYour Name {
52*5113495bSYour Name 	if (!__osif_driver_sync.is_registered)
53*5113495bSYour Name 		return NULL;
54*5113495bSYour Name 
55*5113495bSYour Name 	return &__osif_driver_sync;
56*5113495bSYour Name }
57*5113495bSYour Name 
osif_driver_sync_get(void)58*5113495bSYour Name static struct osif_driver_sync *osif_driver_sync_get(void)
59*5113495bSYour Name {
60*5113495bSYour Name 	if (__osif_driver_sync.in_use)
61*5113495bSYour Name 		return NULL;
62*5113495bSYour Name 
63*5113495bSYour Name 	__osif_driver_sync.in_use = true;
64*5113495bSYour Name 
65*5113495bSYour Name 	return &__osif_driver_sync;
66*5113495bSYour Name }
67*5113495bSYour Name 
osif_driver_sync_put(struct osif_driver_sync * driver_sync)68*5113495bSYour Name static void osif_driver_sync_put(struct osif_driver_sync *driver_sync)
69*5113495bSYour Name {
70*5113495bSYour Name 	qdf_mem_zero(driver_sync, sizeof(*driver_sync));
71*5113495bSYour Name }
72*5113495bSYour Name 
osif_driver_sync_create(struct osif_driver_sync ** out_driver_sync)73*5113495bSYour Name int osif_driver_sync_create(struct osif_driver_sync **out_driver_sync)
74*5113495bSYour Name {
75*5113495bSYour Name 	QDF_STATUS status;
76*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
77*5113495bSYour Name 
78*5113495bSYour Name 	QDF_BUG(out_driver_sync);
79*5113495bSYour Name 	if (!out_driver_sync)
80*5113495bSYour Name 		return -EINVAL;
81*5113495bSYour Name 
82*5113495bSYour Name 	osif_driver_sync_lock();
83*5113495bSYour Name 	driver_sync = osif_driver_sync_get();
84*5113495bSYour Name 	osif_driver_sync_unlock();
85*5113495bSYour Name 	if (!driver_sync)
86*5113495bSYour Name 		return -ENOMEM;
87*5113495bSYour Name 
88*5113495bSYour Name 	status = dsc_driver_create(&driver_sync->dsc_driver);
89*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
90*5113495bSYour Name 		goto sync_put;
91*5113495bSYour Name 
92*5113495bSYour Name 	*out_driver_sync = driver_sync;
93*5113495bSYour Name 
94*5113495bSYour Name 	return 0;
95*5113495bSYour Name 
96*5113495bSYour Name sync_put:
97*5113495bSYour Name 	osif_driver_sync_lock();
98*5113495bSYour Name 	osif_driver_sync_put(driver_sync);
99*5113495bSYour Name 	osif_driver_sync_unlock();
100*5113495bSYour Name 
101*5113495bSYour Name 	return qdf_status_to_os_return(status);
102*5113495bSYour Name }
103*5113495bSYour Name 
104*5113495bSYour Name int
__osif_driver_sync_create_and_trans(struct osif_driver_sync ** out_driver_sync,const char * desc)105*5113495bSYour Name __osif_driver_sync_create_and_trans(struct osif_driver_sync **out_driver_sync,
106*5113495bSYour Name 				    const char *desc)
107*5113495bSYour Name {
108*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
109*5113495bSYour Name 	QDF_STATUS status;
110*5113495bSYour Name 	int errno;
111*5113495bSYour Name 
112*5113495bSYour Name 	errno = osif_driver_sync_create(&driver_sync);
113*5113495bSYour Name 	if (errno)
114*5113495bSYour Name 		return errno;
115*5113495bSYour Name 
116*5113495bSYour Name 	status = dsc_driver_trans_start(driver_sync->dsc_driver, desc);
117*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
118*5113495bSYour Name 		goto sync_destroy;
119*5113495bSYour Name 
120*5113495bSYour Name 	*out_driver_sync = driver_sync;
121*5113495bSYour Name 
122*5113495bSYour Name 	return 0;
123*5113495bSYour Name 
124*5113495bSYour Name sync_destroy:
125*5113495bSYour Name 	osif_driver_sync_destroy(driver_sync);
126*5113495bSYour Name 
127*5113495bSYour Name 	return qdf_status_to_os_return(status);
128*5113495bSYour Name }
129*5113495bSYour Name 
osif_driver_sync_destroy(struct osif_driver_sync * driver_sync)130*5113495bSYour Name void osif_driver_sync_destroy(struct osif_driver_sync *driver_sync)
131*5113495bSYour Name {
132*5113495bSYour Name 	QDF_BUG(driver_sync);
133*5113495bSYour Name 	if (!driver_sync)
134*5113495bSYour Name 		return;
135*5113495bSYour Name 
136*5113495bSYour Name 	dsc_driver_destroy(&driver_sync->dsc_driver);
137*5113495bSYour Name 
138*5113495bSYour Name 	osif_driver_sync_lock();
139*5113495bSYour Name 	osif_driver_sync_put(driver_sync);
140*5113495bSYour Name 	osif_driver_sync_unlock();
141*5113495bSYour Name }
142*5113495bSYour Name 
osif_driver_sync_register(struct osif_driver_sync * driver_sync)143*5113495bSYour Name void osif_driver_sync_register(struct osif_driver_sync *driver_sync)
144*5113495bSYour Name {
145*5113495bSYour Name 	QDF_BUG(driver_sync);
146*5113495bSYour Name 	if (!driver_sync)
147*5113495bSYour Name 		return;
148*5113495bSYour Name 
149*5113495bSYour Name 	osif_driver_sync_lock();
150*5113495bSYour Name 	driver_sync->is_registered = true;
151*5113495bSYour Name 	osif_driver_sync_unlock();
152*5113495bSYour Name }
153*5113495bSYour Name 
osif_driver_sync_unregister(void)154*5113495bSYour Name struct osif_driver_sync *osif_driver_sync_unregister(void)
155*5113495bSYour Name {
156*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
157*5113495bSYour Name 
158*5113495bSYour Name 	osif_driver_sync_lock();
159*5113495bSYour Name 	driver_sync = osif_driver_sync_lookup();
160*5113495bSYour Name 	if (driver_sync)
161*5113495bSYour Name 		driver_sync->is_registered = false;
162*5113495bSYour Name 	osif_driver_sync_unlock();
163*5113495bSYour Name 
164*5113495bSYour Name 	return driver_sync;
165*5113495bSYour Name }
166*5113495bSYour Name 
167*5113495bSYour Name typedef QDF_STATUS (*driver_start_func)(struct dsc_driver *, const char *);
168*5113495bSYour Name 
169*5113495bSYour Name static int
__osif_driver_sync_start_callback(struct osif_driver_sync ** out_driver_sync,const char * desc,driver_start_func driver_start_cb)170*5113495bSYour Name __osif_driver_sync_start_callback(struct osif_driver_sync **out_driver_sync,
171*5113495bSYour Name 				  const char *desc,
172*5113495bSYour Name 				  driver_start_func driver_start_cb)
173*5113495bSYour Name {
174*5113495bSYour Name 	QDF_STATUS status;
175*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
176*5113495bSYour Name 
177*5113495bSYour Name 	*out_driver_sync = NULL;
178*5113495bSYour Name 
179*5113495bSYour Name 	driver_sync = osif_driver_sync_lookup();
180*5113495bSYour Name 	if (!driver_sync)
181*5113495bSYour Name 		return -EAGAIN;
182*5113495bSYour Name 
183*5113495bSYour Name 	status = driver_start_cb(driver_sync->dsc_driver, desc);
184*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
185*5113495bSYour Name 		return qdf_status_to_os_return(status);
186*5113495bSYour Name 
187*5113495bSYour Name 	*out_driver_sync = driver_sync;
188*5113495bSYour Name 
189*5113495bSYour Name 	return 0;
190*5113495bSYour Name }
191*5113495bSYour Name 
192*5113495bSYour Name static int
__osif_driver_sync_start_wait_callback(struct osif_driver_sync ** out_driver_sync,const char * desc,driver_start_func driver_start_cb)193*5113495bSYour Name __osif_driver_sync_start_wait_callback(
194*5113495bSYour Name 				struct osif_driver_sync **out_driver_sync,
195*5113495bSYour Name 				const char *desc,
196*5113495bSYour Name 				driver_start_func driver_start_cb)
197*5113495bSYour Name {
198*5113495bSYour Name 	QDF_STATUS status;
199*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
200*5113495bSYour Name 
201*5113495bSYour Name 	*out_driver_sync = NULL;
202*5113495bSYour Name 
203*5113495bSYour Name 	osif_driver_sync_lock();
204*5113495bSYour Name 	driver_sync = osif_driver_sync_lookup();
205*5113495bSYour Name 	osif_driver_sync_unlock();
206*5113495bSYour Name 	if (!driver_sync)
207*5113495bSYour Name 		return -EAGAIN;
208*5113495bSYour Name 
209*5113495bSYour Name 	status = driver_start_cb(driver_sync->dsc_driver, desc);
210*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
211*5113495bSYour Name 		return qdf_status_to_os_return(status);
212*5113495bSYour Name 
213*5113495bSYour Name 	*out_driver_sync = driver_sync;
214*5113495bSYour Name 
215*5113495bSYour Name 	return 0;
216*5113495bSYour Name }
__osif_driver_sync_trans_start(struct osif_driver_sync ** out_driver_sync,const char * desc)217*5113495bSYour Name int __osif_driver_sync_trans_start(struct osif_driver_sync **out_driver_sync,
218*5113495bSYour Name 				   const char *desc)
219*5113495bSYour Name {
220*5113495bSYour Name 	int errno;
221*5113495bSYour Name 
222*5113495bSYour Name 	osif_driver_sync_lock();
223*5113495bSYour Name 	errno = __osif_driver_sync_start_callback(out_driver_sync, desc,
224*5113495bSYour Name 						  dsc_driver_trans_start);
225*5113495bSYour Name 	osif_driver_sync_unlock();
226*5113495bSYour Name 
227*5113495bSYour Name 	return errno;
228*5113495bSYour Name }
229*5113495bSYour Name 
230*5113495bSYour Name int
__osif_driver_sync_trans_start_wait(struct osif_driver_sync ** out_driver_sync,const char * desc)231*5113495bSYour Name __osif_driver_sync_trans_start_wait(struct osif_driver_sync **out_driver_sync,
232*5113495bSYour Name 				    const char *desc)
233*5113495bSYour Name {
234*5113495bSYour Name 	int errno;
235*5113495bSYour Name 
236*5113495bSYour Name 	/* since dsc_driver_trans_start_wait may sleep do not take lock here */
237*5113495bSYour Name 	errno = __osif_driver_sync_start_wait_callback(out_driver_sync, desc,
238*5113495bSYour Name 			dsc_driver_trans_start_wait);
239*5113495bSYour Name 
240*5113495bSYour Name 	return errno;
241*5113495bSYour Name }
242*5113495bSYour Name 
osif_driver_sync_trans_stop(struct osif_driver_sync * driver_sync)243*5113495bSYour Name void osif_driver_sync_trans_stop(struct osif_driver_sync *driver_sync)
244*5113495bSYour Name {
245*5113495bSYour Name 	dsc_driver_trans_stop(driver_sync->dsc_driver);
246*5113495bSYour Name }
247*5113495bSYour Name 
osif_driver_sync_assert_trans_protected(void)248*5113495bSYour Name void osif_driver_sync_assert_trans_protected(void)
249*5113495bSYour Name {
250*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
251*5113495bSYour Name 
252*5113495bSYour Name 	osif_driver_sync_lock();
253*5113495bSYour Name 
254*5113495bSYour Name 	driver_sync = osif_driver_sync_lookup();
255*5113495bSYour Name 	QDF_BUG(driver_sync);
256*5113495bSYour Name 	if (driver_sync)
257*5113495bSYour Name 		dsc_driver_assert_trans_protected(driver_sync->dsc_driver);
258*5113495bSYour Name 
259*5113495bSYour Name 	osif_driver_sync_unlock();
260*5113495bSYour Name }
261*5113495bSYour Name 
__osif_driver_sync_op_start(struct osif_driver_sync ** out_driver_sync,const char * func)262*5113495bSYour Name int __osif_driver_sync_op_start(struct osif_driver_sync **out_driver_sync,
263*5113495bSYour Name 				const char *func)
264*5113495bSYour Name {
265*5113495bSYour Name 	int errno;
266*5113495bSYour Name 
267*5113495bSYour Name 	osif_driver_sync_lock();
268*5113495bSYour Name 	errno = __osif_driver_sync_start_callback(out_driver_sync, func,
269*5113495bSYour Name 						  _dsc_driver_op_start);
270*5113495bSYour Name 	osif_driver_sync_unlock();
271*5113495bSYour Name 
272*5113495bSYour Name 	return errno;
273*5113495bSYour Name }
274*5113495bSYour Name 
__osif_driver_sync_op_stop(struct osif_driver_sync * driver_sync,const char * func)275*5113495bSYour Name void __osif_driver_sync_op_stop(struct osif_driver_sync *driver_sync,
276*5113495bSYour Name 				const char *func)
277*5113495bSYour Name {
278*5113495bSYour Name 	_dsc_driver_op_stop(driver_sync->dsc_driver, func);
279*5113495bSYour Name }
280*5113495bSYour Name 
osif_driver_sync_wait_for_ops(struct osif_driver_sync * driver_sync)281*5113495bSYour Name void osif_driver_sync_wait_for_ops(struct osif_driver_sync *driver_sync)
282*5113495bSYour Name {
283*5113495bSYour Name 	dsc_driver_wait_for_ops(driver_sync->dsc_driver);
284*5113495bSYour Name }
285*5113495bSYour Name 
osif_driver_sync_init(void)286*5113495bSYour Name void osif_driver_sync_init(void)
287*5113495bSYour Name {
288*5113495bSYour Name 	osif_driver_sync_lock_create();
289*5113495bSYour Name }
290*5113495bSYour Name 
osif_driver_sync_deinit(void)291*5113495bSYour Name void osif_driver_sync_deinit(void)
292*5113495bSYour Name {
293*5113495bSYour Name 	osif_driver_sync_lock_destroy();
294*5113495bSYour Name }
295*5113495bSYour Name 
296*5113495bSYour Name static QDF_STATUS
__osif_driver_sync_dsc_psoc_create(struct dsc_psoc ** out_dsc_psoc)297*5113495bSYour Name __osif_driver_sync_dsc_psoc_create(struct dsc_psoc **out_dsc_psoc)
298*5113495bSYour Name {
299*5113495bSYour Name 	struct osif_driver_sync *driver_sync;
300*5113495bSYour Name 
301*5113495bSYour Name 	driver_sync = osif_driver_sync_lookup();
302*5113495bSYour Name 	if (!driver_sync)
303*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
304*5113495bSYour Name 
305*5113495bSYour Name 	return dsc_psoc_create(driver_sync->dsc_driver, out_dsc_psoc);
306*5113495bSYour Name }
307*5113495bSYour Name 
osif_driver_sync_dsc_psoc_create(struct dsc_psoc ** out_dsc_psoc)308*5113495bSYour Name QDF_STATUS osif_driver_sync_dsc_psoc_create(struct dsc_psoc **out_dsc_psoc)
309*5113495bSYour Name {
310*5113495bSYour Name 	QDF_STATUS status;
311*5113495bSYour Name 
312*5113495bSYour Name 	osif_driver_sync_lock();
313*5113495bSYour Name 	status = __osif_driver_sync_dsc_psoc_create(out_dsc_psoc);
314*5113495bSYour Name 	osif_driver_sync_unlock();
315*5113495bSYour Name 
316*5113495bSYour Name 	return status;
317*5113495bSYour Name }
318*5113495bSYour Name 
319