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