1 /*
2 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*===========================================================================
21 @file VossWrapper.c
22
23 @brief This source file contains the various function definitions for the
24 RTOS abstraction layer, implemented for VOSS
25 ===========================================================================*/
26
27 /*===========================================================================
28
29 EDIT HISTORY FOR FILE
30
31 This section contains comments describing changes made to the module.
32 Notice that changes are listed in reverse chronological order.
33
34 $Header:$ $DateTime: $ $Author: $
35
36 when who what, where, why
37 -------- --- --------------------------------------------------------
38 03/31/09 sho Remove the use of qdf_timerIsActive flag as it is not
39 thread-safe
40 02/17/08 sho Fix the timer callback function to work when it is called
41 after the timer has stopped due to a race condition.
42 02/10/08 sho Refactor the TX timer to use VOS timer directly instead
43 of using VOS utility timer
44 12/15/08 sho Resolved errors and warnings from the AMSS compiler when
45 this is ported from WM
46 11/20/08 sho Renamed this to VosWrapper.c; remove all dependencies on
47 WM platform and allow this to work on all VOSS enabled
48 platform
49 06/24/08 tbh Modified the file to remove the dependency on HDD files as
50 part of Gen6 bring up process.
51 10/29/02 Neelay Das Created file.
52
53 ===========================================================================*/
54
55 /*---------------------------------------------------------------------------
56 * Include Files
57 * ------------------------------------------------------------------------*/
58 #include "sys_wrapper.h"
59
60 #ifdef WLAN_DEBUG
61 #define TIMER_NAME (timer_ptr->timerName)
62 #else
63 #define TIMER_NAME "N/A"
64 #endif
65
66 /**---------------------------------------------------------------------
67 * tx_timer_activate()
68 *
69 * FUNCTION:
70 *
71 * LOGIC:
72 *
73 * ASSUMPTIONS:
74 *
75 * NOTE:
76 *
77 * @param
78 *
79 * @return TX_SUCCESS.
80 *
81 */
tx_timer_activate(TX_TIMER * timer_ptr)82 uint32_t tx_timer_activate(TX_TIMER *timer_ptr)
83 {
84 QDF_STATUS status;
85
86 /* Uncomment the asserts, if the intention is to debug the occurrence of the */
87 /* following anomalous cnditions. */
88
89 /* Assert that the timer structure pointer passed, is not NULL */
90 /* dbgAssert(timer_ptr); */
91
92 /* If the NIC is halting just spoof a successful timer activation, so that all */
93 /* the timers can be cleaned up. */
94
95 if (!timer_ptr)
96 return TX_TIMER_ERROR;
97
98 /* Put a check for the free builds */
99 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) {
100 QDF_ASSERT(timer_ptr->tmrSignature == 0);
101
102 return TX_TIMER_ERROR;
103
104 }
105 /* Check for an uninitialized timer */
106 QDF_ASSERT(0 != strlen(TIMER_NAME));
107
108 status = qdf_mc_timer_start(&timer_ptr->qdf_timer,
109 timer_ptr->initScheduleTimeInMsecs);
110
111 if (QDF_STATUS_SUCCESS == status) {
112 return TX_SUCCESS;
113 } else if (QDF_STATUS_E_ALREADY == status) {
114 /* starting timer fails because timer is already started; this is okay */
115 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_DEBUG,
116 "Timer %s is already running\n", TIMER_NAME);
117 return TX_SUCCESS;
118 } else {
119 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
120 "Timer %s fails to activate\n", TIMER_NAME);
121 return TX_TIMER_ERROR;
122 }
123 } /*** tx_timer_activate() ***/
124
125 /**---------------------------------------------------------------------
126 * tx_timer_change()
127 *
128 * FUNCTION:
129 *
130 * LOGIC:
131 *
132 * ASSUMPTIONS:
133 *
134 * NOTE:
135 *
136 * @param
137 *
138 * @return TX_SUCCESS.
139 *
140 */
tx_timer_change(TX_TIMER * timer_ptr,uint64_t initScheduleTimeInTicks,uint64_t rescheduleTimeInTicks)141 uint32_t tx_timer_change(TX_TIMER *timer_ptr,
142 uint64_t initScheduleTimeInTicks,
143 uint64_t rescheduleTimeInTicks)
144 {
145 /* Put a check for the free builds */
146 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) {
147 QDF_ASSERT(timer_ptr->tmrSignature == 0);
148 return TX_TIMER_ERROR;
149 }
150 /* changes cannot be applied until timer stops running */
151 if (QDF_TIMER_STATE_STOPPED ==
152 qdf_mc_timer_get_current_state(&timer_ptr->qdf_timer)) {
153 timer_ptr->initScheduleTimeInMsecs =
154 TX_MSECS_IN_1_TICK * initScheduleTimeInTicks;
155 timer_ptr->rescheduleTimeInMsecs =
156 TX_MSECS_IN_1_TICK * rescheduleTimeInTicks;
157 return TX_SUCCESS;
158 } else {
159 return TX_TIMER_ERROR;
160 }
161 } /*** tx_timer_change() ***/
162
163 /**---------------------------------------------------------------------
164 * tx_timer_change_context()
165 *
166 * FUNCTION:
167 *
168 * LOGIC:
169 *
170 * ASSUMPTIONS:
171 *
172 * NOTE:
173 *
174 * @param
175 *
176 * @return TX_SUCCESS.
177 *
178 */
tx_timer_change_context(TX_TIMER * timer_ptr,uint32_t expiration_input)179 uint32_t tx_timer_change_context(TX_TIMER *timer_ptr,
180 uint32_t expiration_input)
181 {
182
183 /* Put a check for the free builds */
184 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) {
185 QDF_ASSERT(timer_ptr->tmrSignature == 0);
186
187 return TX_TIMER_ERROR;
188 }
189 /* changes cannot be applied until timer stops running */
190 if (QDF_TIMER_STATE_STOPPED ==
191 qdf_mc_timer_get_current_state(&timer_ptr->qdf_timer)) {
192 timer_ptr->expireInput = expiration_input;
193 return TX_SUCCESS;
194 } else {
195 return TX_TIMER_ERROR;
196 }
197 } /*** tx_timer_change() ***/
198
199 /**---------------------------------------------------------------------
200 * tx_main_timer_func()
201 *
202 * FUNCTION:
203 *
204 * LOGIC:
205 *
206 * ASSUMPTIONS:
207 *
208 * NOTE:
209 *
210 * @param
211 *
212 * @return None.
213 *
214 */
tx_main_timer_func(void * functionContext)215 static void tx_main_timer_func(void *functionContext)
216 {
217 TX_TIMER *timer_ptr = (TX_TIMER *) functionContext;
218
219 if (!timer_ptr) {
220 QDF_ASSERT(0);
221 return;
222 }
223
224 if (!timer_ptr->pExpireFunc) {
225 QDF_ASSERT(0);
226 return;
227 }
228
229 /* Now call the actual timer function, taking the function pointer, */
230 /* from the timer structure. */
231 (*timer_ptr->pExpireFunc)(timer_ptr->mac, timer_ptr->expireInput);
232
233 /* check if this needs to be rescheduled */
234 if (0 != timer_ptr->rescheduleTimeInMsecs) {
235 QDF_STATUS status;
236
237 status = qdf_mc_timer_start(&timer_ptr->qdf_timer,
238 timer_ptr->rescheduleTimeInMsecs);
239 timer_ptr->rescheduleTimeInMsecs = 0;
240
241 if (QDF_STATUS_SUCCESS != status) {
242 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_WARN,
243 "Unable to reschedule timer %s; status=%d",
244 TIMER_NAME, status);
245 }
246 }
247 } /*** tx_timer_change() ***/
248
249 #ifdef TIMER_MANAGER
tx_timer_create_intern_debug(void * pMacGlobal,TX_TIMER * timer_ptr,char * name_ptr,void (* expiration_function)(void *,uint32_t),uint32_t expiration_input,uint64_t initScheduleTimeInTicks,uint64_t rescheduleTimeInTicks,uint64_t auto_activate,char * fileName,uint32_t lineNum)250 uint32_t tx_timer_create_intern_debug(void *pMacGlobal,
251 TX_TIMER *timer_ptr, char *name_ptr,
252 void (*expiration_function)(void *,
253 uint32_t),
254 uint32_t expiration_input,
255 uint64_t initScheduleTimeInTicks,
256 uint64_t rescheduleTimeInTicks,
257 uint64_t auto_activate, char *fileName,
258 uint32_t lineNum)
259 {
260 QDF_STATUS status;
261
262 if (!expiration_function) {
263 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
264 "NULL timer expiration");
265 QDF_ASSERT(0);
266 return TX_TIMER_ERROR;
267 }
268
269 if (!name_ptr) {
270
271 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
272 "NULL name pointer for timer");
273 QDF_ASSERT(0);
274 return TX_TIMER_ERROR;
275 }
276 if (!initScheduleTimeInTicks)
277 return TX_TICK_ERROR;
278
279 if (!timer_ptr)
280 return TX_TIMER_ERROR;
281
282 /* Initialize timer structure */
283 timer_ptr->pExpireFunc = expiration_function;
284 timer_ptr->expireInput = expiration_input;
285 timer_ptr->initScheduleTimeInMsecs =
286 TX_MSECS_IN_1_TICK * initScheduleTimeInTicks;
287 timer_ptr->rescheduleTimeInMsecs =
288 TX_MSECS_IN_1_TICK * rescheduleTimeInTicks;
289 timer_ptr->mac = pMacGlobal;
290
291 /* Set the flag indicating that the timer was created */
292 timer_ptr->tmrSignature = TX_AIRGO_TMR_SIGNATURE;
293
294 #ifdef WLAN_DEBUG
295 /* Store the timer name */
296 strlcpy(timer_ptr->timerName, name_ptr, sizeof(timer_ptr->timerName));
297 #endif /* Store the timer name, for Debug build only */
298
299 status =
300 qdf_mc_timer_init_debug(&timer_ptr->qdf_timer, QDF_TIMER_TYPE_SW,
301 tx_main_timer_func, (void *) timer_ptr,
302 fileName, lineNum);
303 if (QDF_STATUS_SUCCESS != status) {
304 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
305 "Cannot create timer for %s\n", TIMER_NAME);
306 return TX_TIMER_ERROR;
307 }
308
309 if (0 != rescheduleTimeInTicks) {
310 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_DEBUG,
311 "Creating periodic timer for %s\n", TIMER_NAME);
312 }
313 /* Activate this timer if required */
314 if (auto_activate) {
315 tx_timer_activate(timer_ptr);
316 }
317
318 return TX_SUCCESS;
319
320 } /* ** tx_timer_create() *** / */
321 #else
tx_timer_create_intern(void * pMacGlobal,TX_TIMER * timer_ptr,char * name_ptr,void (* expiration_function)(void *,uint32_t),uint32_t expiration_input,uint64_t initScheduleTimeInTicks,uint64_t rescheduleTimeInTicks,uint64_t auto_activate)322 uint32_t tx_timer_create_intern(void *pMacGlobal, TX_TIMER *timer_ptr,
323 char *name_ptr,
324 void (*expiration_function)(void *,
325 uint32_t),
326 uint32_t expiration_input,
327 uint64_t initScheduleTimeInTicks,
328 uint64_t rescheduleTimeInTicks,
329 uint64_t auto_activate)
330 {
331 QDF_STATUS status;
332
333 if ((!name_ptr) || (!expiration_function))
334 return TX_TIMER_ERROR;
335
336 if (!initScheduleTimeInTicks)
337 return TX_TICK_ERROR;
338
339 if (!timer_ptr)
340 return TX_TIMER_ERROR;
341
342 /* Initialize timer structure */
343 timer_ptr->pExpireFunc = expiration_function;
344 timer_ptr->expireInput = expiration_input;
345 timer_ptr->initScheduleTimeInMsecs =
346 TX_MSECS_IN_1_TICK * initScheduleTimeInTicks;
347 timer_ptr->rescheduleTimeInMsecs =
348 TX_MSECS_IN_1_TICK * rescheduleTimeInTicks;
349 timer_ptr->mac = pMacGlobal;
350
351 /* Set the flag indicating that the timer was created */
352 timer_ptr->tmrSignature = TX_AIRGO_TMR_SIGNATURE;
353
354 #ifdef WLAN_DEBUG
355 /* Store the timer name */
356 strlcpy(timer_ptr->timerName, name_ptr, sizeof(timer_ptr->timerName));
357 #endif /* Store the timer name, for Debug build only */
358
359 status = qdf_mc_timer_init(&timer_ptr->qdf_timer, QDF_TIMER_TYPE_SW,
360 tx_main_timer_func, (void *) timer_ptr);
361 if (QDF_STATUS_SUCCESS != status) {
362 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
363 "Cannot create timer for %s\n", TIMER_NAME);
364 return TX_TIMER_ERROR;
365 }
366
367 if (0 != rescheduleTimeInTicks) {
368 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
369 "Creating periodic timer for %s\n", TIMER_NAME);
370 }
371 /* Activate this timer if required */
372 if (auto_activate) {
373 tx_timer_activate(timer_ptr);
374 }
375
376 return TX_SUCCESS;
377
378 } /* ** tx_timer_create() *** / */
379 #endif
380
381 /**---------------------------------------------------------------------
382 * tx_timer_deactivate()
383 *
384 * FUNCTION:
385 *
386 * LOGIC:
387 *
388 * ASSUMPTIONS:
389 *
390 * NOTE:
391 *
392 * @param
393 *
394 * @return TX_SUCCESS.
395 *
396 */
tx_timer_deactivate(TX_TIMER * timer_ptr)397 uint32_t tx_timer_deactivate(TX_TIMER *timer_ptr)
398 {
399 QDF_STATUS vStatus;
400
401 /* Put a check for the free builds */
402 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) {
403 return TX_TIMER_ERROR;
404 }
405 /* if the timer is not running then we do not need to do anything here */
406 vStatus = qdf_mc_timer_stop(&timer_ptr->qdf_timer);
407 if (QDF_STATUS_SUCCESS != vStatus) {
408 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO_HIGH,
409 "Unable to stop timer %s; status =%d\n",
410 TIMER_NAME, vStatus);
411 }
412
413 return TX_SUCCESS;
414
415 } /*** tx_timer_deactivate() ***/
416
tx_timer_delete(TX_TIMER * timer_ptr)417 uint32_t tx_timer_delete(TX_TIMER *timer_ptr)
418 {
419 /* Put a check for the free builds */
420 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) {
421 return TX_TIMER_ERROR;
422 }
423
424 qdf_mc_timer_destroy(&timer_ptr->qdf_timer);
425 timer_ptr->tmrSignature = 0;
426
427 return TX_SUCCESS;
428 } /*** tx_timer_delete() ***/
429
430 /**---------------------------------------------------------------------
431 * tx_timer_running()
432 *
433 * FUNCTION:
434 *
435 * LOGIC:
436 *
437 * ASSUMPTIONS:
438 *
439 * NOTE:
440 *
441 * @param
442 *
443 * @return TX_SUCCESS.
444 *
445 */
tx_timer_running(TX_TIMER * timer_ptr)446 bool tx_timer_running(TX_TIMER *timer_ptr)
447 {
448 /* Put a check for the free builds */
449 if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature)
450 return false;
451
452 if (QDF_TIMER_STATE_RUNNING ==
453 qdf_mc_timer_get_current_state(&timer_ptr->qdf_timer)) {
454 return true;
455 }
456 return false;
457
458 } /*** tx_timer_running() ***/
459