xref: /wlan-dirver/qca-wifi-host-cmn/qdf/inc/qdf_time.h (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2014-2021 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 /**
20  * DOC: qdf_time
21  * This file abstracts time related functionality.
22  */
23 
24 #ifndef _QDF_OS_TIME_H
25 #define _QDF_OS_TIME_H
26 
27 #include <i_qdf_time.h>
28 
29 typedef __qdf_time_t qdf_time_t;
30 typedef __qdf_ktime_t qdf_ktime_t;
31 typedef __qdf_timespec_t qdf_timespec_t;
32 typedef __qdf_work_struct_t qdf_work_struct_t;
33 
34 #ifdef ENHANCED_OS_ABSTRACTION
35 /**
36  * qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
37  * @ns: time in nanoseconds
38  *
39  * Return: nanoseconds as qdf_ktime_t object
40  */
41 qdf_ktime_t qdf_ns_to_ktime(uint64_t ns);
42 
43 /**
44  * qdf_ktime_add - Adds two qdf_ktime_t objects and returns
45  * a qdf_ktime_t object
46  * @ktime1: time as qdf_ktime_t object
47  * @ktime2: time as qdf_ktime_t object
48  *
49  * Return: sum of both qdf_ktime_t as qdf_ktime_t object
50  */
51 qdf_ktime_t qdf_ktime_add(qdf_ktime_t ktime1, qdf_ktime_t ktime2);
52 
53 /**
54  * qdf_ktime_get - Gets the current time as qdf_ktime_t object
55  *
56  * Return: current time as qdf_ktime_t object
57  */
58 qdf_ktime_t qdf_ktime_get(void);
59 
60 /**
61  * qdf_ktime_real_get - Gets the current wall clock as qdf_ktime_t object
62  *
63  * Return: current wall clock as qdf_ktime_t object
64  */
65 qdf_ktime_t qdf_ktime_real_get(void);
66 
67 /**
68  * qdf_ktime_add_ns - Adds qdf_ktime_t object and nanoseconds value and
69  * returns the qdf_ktime_t object
70  * @ktime: time as qdf_ktime_t object
71  * @ns: time in nanoseconds
72  *
73  * Return: qdf_ktime_t object
74  */
75 qdf_ktime_t qdf_ktime_add_ns(qdf_ktime_t ktime, int64_t ns);
76 
77 /**
78  * qdf_ktime_to_ms - Convert the qdf_ktime_t object into milliseconds
79  * @ktime: time as qdf_ktime_t object
80  *
81  * Return: qdf_ktime_t in milliseconds
82  */
83 int64_t qdf_ktime_to_ms(qdf_ktime_t ktime);
84 
85 /**
86  * qdf_ktime_to_ns - Convert the qdf_ktime_t object into nanoseconds
87  * @ktime: time as qdf_ktime_t object
88  *
89  * Return: qdf_ktime_t in nanoseconds
90  */
91 int64_t qdf_ktime_to_ns(qdf_ktime_t ktime);
92 
93 /**
94  * qdf_system_ticks - Count the number of ticks elapsed from the time when
95  * the system booted
96  *
97  * Return: ticks
98  */
99 qdf_time_t qdf_system_ticks(void);
100 
101 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
102 
103 /**
104  * qdf_system_ticks_to_msecs - convert ticks to milliseconds
105  * @clock_ticks: Number of ticks
106  *
107  * Return: unsigned int Time in milliseconds
108  */
109 uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks);
110 
111 /**
112  * qdf_system_msecs_to_ticks - convert milliseconds to ticks
113  * @msec: Time in milliseconds
114  *
115  * Return: unsigned long number of ticks
116  */
117 qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs);
118 
119 /**
120  * qdf_get_system_uptime - Return a monotonically increasing time
121  * This increments once per HZ ticks
122  *
123  * Return: qdf_time_t system up time in ticks
124  */
125 qdf_time_t qdf_get_system_uptime(void);
126 
127 /**
128  * qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
129  *
130  * qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
131  * that have elapsed since the system was booted. It also includes the time when
132  * system was suspended.
133  *
134  * Return:
135  * The time since system booted in nanoseconds
136  */
137 uint64_t qdf_get_bootbased_boottime_ns(void);
138 
139 /**
140  * qdf_get_system_timestamp - Return current timestamp
141  *
142  * Return: unsigned long timestamp in ms.
143  */
144 unsigned long qdf_get_system_timestamp(void);
145 
146 /**
147  * qdf_udelay - delay in microseconds
148  * @usecs: Number of microseconds to delay
149  *
150  * Return: none
151  */
152 void qdf_udelay(int usecs);
153 
154 /**
155  * qdf_mdelay - Delay in milliseconds.
156  * @msec: Number of milliseconds to delay
157  *
158  * Return: none
159  */
160 void qdf_mdelay(int msecs);
161 
162 /**
163  * qdf_system_time_after() - Check if a is later than b
164  * @a: Time stamp value a
165  * @b: Time stamp value b
166  *
167  * Return: true if a < b else false
168  */
169 bool qdf_system_time_after(qdf_time_t a, qdf_time_t b);
170 
171 /**
172  * qdf_system_time_before() - Check if a is before b
173  * @a: Time stamp value a
174  * @b: Time stamp value b
175  *
176  * Return: true if a is before b else false
177  */
178 bool qdf_system_time_before(qdf_time_t a, qdf_time_t b);
179 
180 /**
181  * qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
182  * later
183  * @a: Time stamp value a
184  * @b: Time stamp value b
185  *
186  * Return: true if a >= b else false
187  */
188 bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b);
189 
190 /**
191  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
192  * @KERNEL_LOG: boottime time in uS (micro seconds)
193  * @QTIMER: QTIME in (1/19200)S
194  *
195  * This enum is used to distinguish which timer source is used.
196  */
197 enum qdf_timestamp_unit {
198 	KERNEL_LOG,
199 	QTIMER,
200 };
201 
202 #ifdef MSM_PLATFORM
203 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
204 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
205 #else
206 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
207 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
208 #endif /* end of MSM_PLATFORM */
209 
210 uint64_t qdf_log_timestamp_to_usecs(uint64_t time);
211 
212 /**
213  * qdf_get_log_timestamp_to_secs() - get time stamp for logging in seconds
214  *
215  * Return: The current logging timestamp normalized to second precision
216  */
217 void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
218 			       uint64_t *usecs);
219 
220 uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs);
221 
222 /**
223  * qdf_get_log_timestamp - get time stamp for logging
224  * For adrastea this API returns QTIMER tick which is needed to synchronize
225  * host and fw log timestamps
226  * For ROME and other discrete solution this API returns system boot time stamp
227  *
228  * Return:
229  * QTIMER ticks(19.2MHz) for adrastea
230  * System tick for rome and other future discrete solutions
231  */
232 uint64_t qdf_get_log_timestamp(void);
233 
234 /**
235  * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds
236  *
237  * Return: The current logging timestamp normalized to microsecond precision
238  */
239 uint64_t qdf_get_log_timestamp_usecs(void);
240 
241 /**
242  * qdf_get_monotonic_boottime - get monotonic kernel boot time
243  * This API is similar to qdf_get_system_boottime but it includes
244  * time spent in suspend.
245  *
246  * Return: Time in microseconds
247  */
248 uint64_t qdf_get_monotonic_boottime(void);
249 
250 /**
251  * qdf_time_ktime_get_real_time() - Get the time of day in qdf_timespec_t
252  * @ts: pointer to the qdf_timespec_t
253  *
254  * Return: None
255  */
256 void qdf_time_ktime_get_real_time(qdf_timespec_t *ts);
257 
258 /**
259  * qdf_time_sched_clock - scheduler clock
260  *
261  * Return: current time in nanosec units.
262  */
263 unsigned long long qdf_time_sched_clock(void);
264 #else
265 /**
266  * qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
267  * @ns: time in nanoseconds
268  *
269  * Return: nanoseconds as qdf_ktime_t object
270  */
271 
272 static inline qdf_ktime_t qdf_ns_to_ktime(uint64_t ns)
273 {
274 	return __qdf_ns_to_ktime(ns);
275 }
276 
277 /**
278  * qdf_ktime_add - Adds two qdf_ktime_t objects and returns
279  * a qdf_ktime_t object
280  * @ktime1: time as qdf_ktime_t object
281  * @ktime2: time as qdf_ktime_t object
282  *
283  * Return: sum of both qdf_ktime_t as qdf_ktime_t object
284  */
285 
286 static inline qdf_ktime_t qdf_ktime_add(qdf_ktime_t ktime1, qdf_ktime_t ktime2)
287 {
288 	return __qdf_ktime_add(ktime1, ktime2);
289 }
290 
291 /**
292  * qdf_ktime_get - Gets the current time as qdf_ktime_t object
293  *
294  * Return: current time as qdf_ktime_t object
295  */
296 
297 static inline qdf_ktime_t qdf_ktime_get(void)
298 {
299 	return __qdf_ktime_get();
300 }
301 
302 /**
303  * qdf_ktime_real_get - Gets the current wall clock as qdf_ktime_t object
304  *
305  * Return: current wall clock as qdf_ktime_t object
306  */
307 
308 static inline qdf_ktime_t qdf_ktime_real_get(void)
309 {
310 	return __qdf_ktime_real_get();
311 }
312 
313 /**
314  * qdf_ktime_add_ns - Adds qdf_ktime_t object and nanoseconds value and
315  * returns the qdf_ktime_t object
316  * @ktime: time as qdf_ktime_t object
317  * @ns: time in nanoseconds
318  *
319  * Return: qdf_ktime_t object
320  */
321 
322 static inline qdf_ktime_t qdf_ktime_add_ns(qdf_ktime_t ktime, int64_t ns)
323 {
324 	return __qdf_ktime_add_ns(ktime, ns);
325 }
326 
327 /**
328  * qdf_ktime_to_ms - Convert the qdf_ktime_t object into milliseconds
329  * @ktime: time as qdf_ktime_t object
330  *
331  * Return: qdf_ktime_t in milliseconds
332  */
333 
334 static inline int64_t qdf_ktime_to_ms(qdf_ktime_t ktime)
335 {
336 	return __qdf_ktime_to_ms(ktime);
337 }
338 
339 /**
340  * qdf_ktime_to_ns - Convert the qdf_ktime_t object into nanoseconds
341  * @ktime: time as qdf_ktime_t object
342  *
343  * Return: qdf_ktime_t in nanoseconds
344  */
345 
346 static inline int64_t qdf_ktime_to_ns(qdf_ktime_t ktime)
347 {
348 	return __qdf_ktime_to_ns(ktime);
349 }
350 
351 /**
352  * qdf_system_ticks - Count the number of ticks elapsed from the time when
353  * the system booted
354  *
355  * Return: ticks
356  */
357 static inline qdf_time_t qdf_system_ticks(void)
358 {
359 	return __qdf_system_ticks();
360 }
361 
362 #define qdf_system_ticks_per_sec __qdf_system_ticks_per_sec
363 
364 /**
365  * qdf_system_ticks_to_msecs - convert ticks to milliseconds
366  * @clock_ticks: Number of ticks
367  *
368  * Return: unsigned int Time in milliseconds
369  */
370 static inline uint32_t qdf_system_ticks_to_msecs(unsigned long clock_ticks)
371 {
372 	return __qdf_system_ticks_to_msecs(clock_ticks);
373 }
374 
375 /**
376  * qdf_system_msecs_to_ticks - convert milliseconds to ticks
377  * @msec: Time in milliseconds
378  *
379  * Return: unsigned long number of ticks
380  */
381 static inline qdf_time_t qdf_system_msecs_to_ticks(uint32_t msecs)
382 {
383 	return __qdf_system_msecs_to_ticks(msecs);
384 }
385 
386 /**
387  * qdf_get_system_uptime - Return a monotonically increasing time
388  * This increments once per HZ ticks
389  *
390  * Return: qdf_time_t system up time in ticks
391  */
392 static inline qdf_time_t qdf_get_system_uptime(void)
393 {
394 	return __qdf_get_system_uptime();
395 }
396 
397 /**
398  * qdf_get_bootbased_boottime_ns() - Get the bootbased time in nanoseconds
399  *
400  * qdf_get_bootbased_boottime_ns() function returns the number of nanoseconds
401  * that have elapsed since the system was booted. It also includes the time when
402  * system was suspended.
403  *
404  * Return:
405  * The time since system booted in nanoseconds
406  */
407 
408 static inline uint64_t qdf_get_bootbased_boottime_ns(void)
409 {
410 	return __qdf_get_bootbased_boottime_ns();
411 }
412 
413 /**
414  * qdf_get_system_timestamp - Return current timestamp
415  *
416  * Return: unsigned long timestamp in ms.
417  */
418 static inline unsigned long qdf_get_system_timestamp(void)
419 {
420 	return __qdf_get_system_timestamp();
421 }
422 
423 /**
424  * qdf_udelay - delay in microseconds
425  * @usecs: Number of microseconds to delay
426  *
427  * Return: none
428  */
429 static inline void qdf_udelay(int usecs)
430 {
431 	__qdf_udelay(usecs);
432 }
433 
434 /**
435  * qdf_mdelay - Delay in milliseconds.
436  * @msec: Number of milliseconds to delay
437  *
438  * Return: none
439  */
440 static inline void qdf_mdelay(int msecs)
441 {
442 	__qdf_mdelay(msecs);
443 }
444 
445 /**
446  * qdf_system_time_after() - Check if a is later than b
447  * @a: Time stamp value a
448  * @b: Time stamp value b
449  *
450  * Return:
451  * true if a < b else false
452  */
453 static inline bool qdf_system_time_after(qdf_time_t a, qdf_time_t b)
454 {
455 	return __qdf_system_time_after(a, b);
456 }
457 
458 /**
459  * qdf_system_time_before() - Check if a is before b
460  * @a: Time stamp value a
461  * @b: Time stamp value b
462  *
463  * Return:
464  * true if a is before b else false
465  */
466 static inline bool qdf_system_time_before(qdf_time_t a, qdf_time_t b)
467 {
468 	return __qdf_system_time_before(a, b);
469 }
470 
471 /**
472  * qdf_system_time_after_eq() - Check if a atleast as recent as b, if not
473  * later
474  * @a: Time stamp value a
475  * @b: Time stamp value b
476  *
477  * Return:
478  * true if a >= b else false
479  */
480 static inline bool qdf_system_time_after_eq(qdf_time_t a, qdf_time_t b)
481 {
482 	return __qdf_system_time_after_eq(a, b);
483 }
484 
485 /**
486  * qdf_sched_clock() - use light weight timer to get timestamp for logging
487  *
488  * Return: timestamp in ns
489  */
490 static inline uint64_t qdf_sched_clock(void)
491 {
492 	return __qdf_sched_clock();
493 }
494 
495 /**
496  * enum qdf_timestamp_unit - what unit the qdf timestamp is in
497  * @KERNEL_LOG: boottime time in uS (micro seconds)
498  * @QTIMER: QTIME in (1/19200)S
499  *
500  * This enum is used to distinguish which timer source is used.
501  */
502 enum qdf_timestamp_unit {
503 	KERNEL_LOG,
504 	QTIMER,
505 };
506 
507 #ifdef MSM_PLATFORM
508 #define QDF_LOG_TIMESTAMP_UNIT QTIMER
509 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 192
510 
511 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
512 {
513 	/*
514 	 * Try to preserve precision by multiplying by 10 first.
515 	 * If that would cause a wrap around, divide first instead.
516 	 */
517 	if (time * 10 < time) {
518 		do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
519 		return time * 10;
520 	}
521 
522 	time = time * 10;
523 	do_div(time, QDF_LOG_TIMESTAMP_CYCLES_PER_10_US);
524 
525 	return time;
526 }
527 
528 /**
529  * qdf_get_log_timestamp_lightweight - get time stamp for logging
530  * For adrastea this API returns QTIMER tick which is needed to synchronize
531  * host and fw log timestamps
532  * For ROME and other discrete solution this API returns system boot time stamp
533  *
534  * Return:
535  * QTIMER ticks(19.2MHz) for adrastea
536  * System tick for rome and other 3rd party platform solutions
537  */
538 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
539 {
540 	return __qdf_get_log_timestamp();
541 }
542 #else
543 #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG
544 #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10
545 
546 static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time)
547 {
548 	/* timestamps are already in micro seconds */
549 	return time;
550 }
551 
552 static inline uint64_t qdf_get_log_timestamp_lightweight(void)
553 {
554 	uint64_t timestamp_us;
555 
556 	/* explicitly change to uint64_t, otherwise it will assign
557 	 * uint32_t to timestamp_us, which lose high 32bits.
558 	 * on 64bit platform, it will only use low 32bits jiffies in
559 	 * jiffies_to_msecs.
560 	 * eg: HZ=250, it will overflow every (0xffff ffff<<2==0x3fff ffff)
561 	 * ticks. it is 1193 hours.
562 	 */
563 	timestamp_us =
564 	(uint64_t)__qdf_system_ticks_to_msecs(qdf_system_ticks()) * 1000;
565 	return timestamp_us;
566 }
567 #endif /* end of MSM_PLATFORM */
568 
569 static inline void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs,
570 					     uint64_t *usecs)
571 {
572 	*secs = qdf_log_timestamp_to_usecs(time);
573 	*usecs = do_div(*secs, 1000000ul);
574 }
575 
576 static inline uint64_t qdf_usecs_to_log_timestamp(uint64_t usecs)
577 {
578 	return (usecs * QDF_LOG_TIMESTAMP_CYCLES_PER_10_US) / 10;
579 }
580 
581 /**
582  * qdf_get_log_timestamp - get time stamp for logging
583  * For adrastea this API returns QTIMER tick which is needed to synchronize
584  * host and fw log timestamps
585  * For ROME and other discrete solution this API returns system boot time stamp
586  *
587  * Return:
588  * QTIMER ticks(19.2MHz) for adrastea
589  * System tick for rome and other future discrete solutions
590  */
591 static inline uint64_t qdf_get_log_timestamp(void)
592 {
593 	return __qdf_get_log_timestamp();
594 }
595 
596 /**
597  * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds
598  *
599  * Return: The current logging timestamp normalized to microsecond precision
600  */
601 static inline uint64_t qdf_get_log_timestamp_usecs(void)
602 {
603 	return qdf_log_timestamp_to_usecs(qdf_get_log_timestamp());
604 }
605 
606 /**
607  * qdf_get_monotonic_boottime - get monotonic kernel boot time
608  * This API is similar to qdf_get_system_boottime but it includes
609  * time spent in suspend.
610  *
611  * Return: Time in microseconds
612  */
613 static inline uint64_t qdf_get_monotonic_boottime(void)
614 {
615 	return __qdf_get_monotonic_boottime();
616 }
617 
618 static inline void qdf_time_ktime_get_real_time(qdf_timespec_t *ts)
619 {
620 	return __qdf_time_ktime_get_real_time(ts);
621 }
622 
623 static inline unsigned long long qdf_time_sched_clock(void)
624 {
625 	return __qdf_time_sched_clock();
626 }
627 #endif
628 
629 #endif
630