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