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