1 /*
2 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include "qdf_list.h"
20 #include "qdf_mem.h"
21 #include "qdf_status.h"
22 #include "qdf_types.h"
23 #include "__wlan_dsc.h"
24 #include "wlan_dsc.h"
25
__dsc_lock(struct dsc_driver * driver)26 void __dsc_lock(struct dsc_driver *driver)
27 {
28 dsc_assert(driver);
29 qdf_spin_lock_bh(&driver->lock);
30 }
31
__dsc_unlock(struct dsc_driver * driver)32 void __dsc_unlock(struct dsc_driver *driver)
33 {
34 dsc_assert(driver);
35 qdf_spin_unlock_bh(&driver->lock);
36 }
37
__dsc_driver_create(struct dsc_driver ** out_driver)38 static QDF_STATUS __dsc_driver_create(struct dsc_driver **out_driver)
39 {
40 struct dsc_driver *driver;
41
42 if (!dsc_assert(out_driver))
43 return QDF_STATUS_E_INVAL;
44
45 *out_driver = NULL;
46
47 driver = qdf_mem_malloc(sizeof(*driver));
48 if (!driver)
49 return QDF_STATUS_E_NOMEM;
50
51 qdf_spinlock_create(&driver->lock);
52 qdf_list_create(&driver->psocs, 0);
53 __dsc_trans_init(&driver->trans);
54 __dsc_ops_init(&driver->ops);
55
56 *out_driver = driver;
57
58 return QDF_STATUS_SUCCESS;
59 }
60
dsc_driver_create(struct dsc_driver ** out_driver)61 QDF_STATUS dsc_driver_create(struct dsc_driver **out_driver)
62 {
63 QDF_STATUS status;
64
65 status = __dsc_driver_create(out_driver);
66
67 return status;
68 }
69
__dsc_driver_destroy(struct dsc_driver ** out_driver)70 static void __dsc_driver_destroy(struct dsc_driver **out_driver)
71 {
72 struct dsc_driver *driver;
73
74 if (!dsc_assert(out_driver))
75 return;
76
77 driver = *out_driver;
78 if (!dsc_assert(driver))
79 return;
80
81 *out_driver = NULL;
82
83 /* assert no children */
84 dsc_assert(qdf_list_empty(&driver->psocs));
85
86 /* flush pending transitions */
87 while (__dsc_trans_abort(&driver->trans))
88 ;
89
90 /* de-init */
91 __dsc_ops_deinit(&driver->ops);
92 __dsc_trans_deinit(&driver->trans);
93 qdf_list_destroy(&driver->psocs);
94 qdf_spinlock_destroy(&driver->lock);
95
96 qdf_mem_free(driver);
97 }
98
dsc_driver_destroy(struct dsc_driver ** out_driver)99 void dsc_driver_destroy(struct dsc_driver **out_driver)
100 {
101 __dsc_driver_destroy(out_driver);
102 }
103
__dsc_driver_trans_active_down_tree(struct dsc_driver * driver)104 static bool __dsc_driver_trans_active_down_tree(struct dsc_driver *driver)
105 {
106 struct dsc_psoc *psoc;
107 struct dsc_vdev *vdev;
108
109 dsc_for_each_driver_psoc(driver, psoc) {
110 if (__dsc_trans_active(&psoc->trans))
111 return true;
112
113 dsc_for_each_psoc_vdev(psoc, vdev) {
114 if (__dsc_trans_active(&vdev->trans))
115 return true;
116 }
117 }
118
119 return false;
120 }
121
122 #define __dsc_driver_can_op(driver) __dsc_driver_can_trans(driver)
123
__dsc_driver_can_trans(struct dsc_driver * driver)124 static bool __dsc_driver_can_trans(struct dsc_driver *driver)
125 {
126 return !__dsc_trans_active_or_queued(&driver->trans) &&
127 !__dsc_driver_trans_active_down_tree(driver);
128 }
129
__dsc_driver_can_trigger(struct dsc_driver * driver)130 static bool __dsc_driver_can_trigger(struct dsc_driver *driver)
131 {
132 return !__dsc_trans_active(&driver->trans) &&
133 !__dsc_driver_trans_active_down_tree(driver);
134 }
135
136 static QDF_STATUS
__dsc_driver_trans_start_nolock(struct dsc_driver * driver,const char * desc)137 __dsc_driver_trans_start_nolock(struct dsc_driver *driver, const char *desc)
138 {
139 if (!__dsc_driver_can_trans(driver))
140 return QDF_STATUS_E_AGAIN;
141
142 return __dsc_trans_start(&driver->trans, desc);
143 }
144
145 static QDF_STATUS
__dsc_driver_trans_start(struct dsc_driver * driver,const char * desc)146 __dsc_driver_trans_start(struct dsc_driver *driver, const char *desc)
147 {
148 QDF_STATUS status;
149
150 if (!dsc_assert(driver))
151 return QDF_STATUS_E_INVAL;
152
153 if (!dsc_assert(desc))
154 return QDF_STATUS_E_INVAL;
155
156 __dsc_lock(driver);
157 status = __dsc_driver_trans_start_nolock(driver, desc);
158 __dsc_unlock(driver);
159
160 return status;
161 }
162
dsc_driver_trans_start(struct dsc_driver * driver,const char * desc)163 QDF_STATUS dsc_driver_trans_start(struct dsc_driver *driver, const char *desc)
164 {
165 QDF_STATUS status;
166
167 dsc_enter_str(desc);
168 status = __dsc_driver_trans_start(driver, desc);
169 if (QDF_IS_STATUS_ERROR(status))
170 dsc_exit_status(status);
171
172 return status;
173 }
174
175 static QDF_STATUS
__dsc_driver_trans_start_wait(struct dsc_driver * driver,const char * desc)176 __dsc_driver_trans_start_wait(struct dsc_driver *driver, const char *desc)
177 {
178 QDF_STATUS status;
179 struct dsc_tran tran = { 0 };
180
181 if (!dsc_assert(driver))
182 return QDF_STATUS_E_INVAL;
183
184 if (!dsc_assert(desc))
185 return QDF_STATUS_E_INVAL;
186
187 __dsc_lock(driver);
188
189 /* try to start without waiting */
190 status = __dsc_driver_trans_start_nolock(driver, desc);
191 if (QDF_IS_STATUS_SUCCESS(status))
192 goto unlock;
193
194 status = __dsc_trans_queue(&driver->trans, &tran, desc);
195 if (QDF_IS_STATUS_ERROR(status))
196 goto unlock;
197
198 __dsc_unlock(driver);
199
200 return __dsc_tran_wait(&tran);
201
202 unlock:
203 __dsc_unlock(driver);
204
205 return status;
206 }
207
208 QDF_STATUS
dsc_driver_trans_start_wait(struct dsc_driver * driver,const char * desc)209 dsc_driver_trans_start_wait(struct dsc_driver *driver, const char *desc)
210 {
211 QDF_STATUS status;
212
213 dsc_enter_str(desc);
214 status = __dsc_driver_trans_start_wait(driver, desc);
215 if (QDF_IS_STATUS_ERROR(status))
216 dsc_exit_status(status);
217
218 return status;
219 }
220
__dsc_driver_trans_trigger_checked(struct dsc_driver * driver)221 bool __dsc_driver_trans_trigger_checked(struct dsc_driver *driver)
222 {
223 if (!__dsc_trans_queued(&driver->trans))
224 return false;
225
226 /* handled, but don't trigger; we need to wait for more children */
227 if (!__dsc_driver_can_trigger(driver))
228 return true;
229
230 return __dsc_trans_trigger(&driver->trans);
231 }
232
__dsc_driver_trigger_trans(struct dsc_driver * driver)233 static void __dsc_driver_trigger_trans(struct dsc_driver *driver)
234 {
235 struct dsc_psoc *psoc;
236 struct dsc_vdev *vdev;
237
238 if (__dsc_trans_trigger(&driver->trans))
239 return;
240
241 dsc_for_each_driver_psoc(driver, psoc) {
242 if (__dsc_trans_trigger(&psoc->trans))
243 continue;
244
245 dsc_for_each_psoc_vdev(psoc, vdev)
246 __dsc_trans_trigger(&vdev->trans);
247 }
248 }
249
__dsc_driver_trans_stop(struct dsc_driver * driver)250 static void __dsc_driver_trans_stop(struct dsc_driver *driver)
251 {
252 if (!dsc_assert(driver))
253 return;
254
255 __dsc_lock(driver);
256
257 __dsc_trans_stop(&driver->trans);
258 __dsc_driver_trigger_trans(driver);
259
260 __dsc_unlock(driver);
261 }
262
dsc_driver_trans_stop(struct dsc_driver * driver)263 void dsc_driver_trans_stop(struct dsc_driver *driver)
264 {
265 __dsc_driver_trans_stop(driver);
266 }
267
__dsc_driver_assert_trans_protected(struct dsc_driver * driver)268 static void __dsc_driver_assert_trans_protected(struct dsc_driver *driver)
269 {
270 if (!dsc_assert(driver))
271 return;
272
273 __dsc_lock(driver);
274 dsc_assert(__dsc_trans_active(&driver->trans));
275 __dsc_unlock(driver);
276 }
277
dsc_driver_assert_trans_protected(struct dsc_driver * driver)278 void dsc_driver_assert_trans_protected(struct dsc_driver *driver)
279 {
280 __dsc_driver_assert_trans_protected(driver);
281 }
282
283 static QDF_STATUS
__dsc_driver_op_start(struct dsc_driver * driver,const char * func)284 __dsc_driver_op_start(struct dsc_driver *driver, const char *func)
285 {
286 QDF_STATUS status;
287
288 if (!dsc_assert(driver))
289 return QDF_STATUS_E_INVAL;
290
291 if (!dsc_assert(func))
292 return QDF_STATUS_E_INVAL;
293
294 __dsc_lock(driver);
295
296 if (!__dsc_driver_can_op(driver)) {
297 status = QDF_STATUS_E_AGAIN;
298 goto unlock;
299 }
300
301 status = __dsc_ops_insert(&driver->ops, func);
302
303 unlock:
304 __dsc_unlock(driver);
305
306 return status;
307 }
308
_dsc_driver_op_start(struct dsc_driver * driver,const char * func)309 QDF_STATUS _dsc_driver_op_start(struct dsc_driver *driver, const char *func)
310 {
311 QDF_STATUS status;
312
313 dsc_enter_str(func);
314 status = __dsc_driver_op_start(driver, func);
315 if (QDF_IS_STATUS_ERROR(status))
316 dsc_exit_status(status);
317
318 return status;
319 }
320
__dsc_driver_op_stop(struct dsc_driver * driver,const char * func)321 static void __dsc_driver_op_stop(struct dsc_driver *driver, const char *func)
322 {
323 if (!dsc_assert(driver))
324 return;
325
326 if (!dsc_assert(func))
327 return;
328
329 __dsc_lock(driver);
330 if (__dsc_ops_remove(&driver->ops, func))
331 qdf_event_set(&driver->ops.event);
332 __dsc_unlock(driver);
333 }
334
_dsc_driver_op_stop(struct dsc_driver * driver,const char * func)335 void _dsc_driver_op_stop(struct dsc_driver *driver, const char *func)
336 {
337 __dsc_driver_op_stop(driver, func);
338 }
339
__dsc_driver_wait_for_ops(struct dsc_driver * driver)340 static void __dsc_driver_wait_for_ops(struct dsc_driver *driver)
341 {
342 struct dsc_psoc *psoc;
343 bool wait;
344
345 if (!dsc_assert(driver))
346 return;
347
348 __dsc_lock(driver);
349
350 /* flushing without preventing new ops is almost certainly a bug */
351 dsc_assert(!__dsc_driver_can_op(driver));
352
353 wait = driver->ops.count > 0;
354 if (wait)
355 qdf_event_reset(&driver->ops.event);
356
357 __dsc_unlock(driver);
358
359 if (wait)
360 qdf_wait_single_event(&driver->ops.event, 0);
361
362 /* wait for down-tree ops to complete as well */
363 dsc_for_each_driver_psoc(driver, psoc)
364 dsc_psoc_wait_for_ops(psoc);
365 }
366
dsc_driver_wait_for_ops(struct dsc_driver * driver)367 void dsc_driver_wait_for_ops(struct dsc_driver *driver)
368 {
369 __dsc_driver_wait_for_ops(driver);
370 }
371
372