|
@@ -48,6 +48,18 @@ extern struct tvec_base boot_tvec_bases;
|
|
#define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn)
|
|
#define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Note that all tvec_bases are 2 byte aligned and lower bit of
|
|
|
|
+ * base in timer_list is guaranteed to be zero. Use the LSB to
|
|
|
|
+ * indicate whether the timer is deferrable.
|
|
|
|
+ *
|
|
|
|
+ * A deferrable timer will work normally when the system is busy, but
|
|
|
|
+ * will not cause a CPU to come out of idle just to service it; instead,
|
|
|
|
+ * the timer will be serviced when the CPU eventually wakes up with a
|
|
|
|
+ * subsequent non-deferrable timer.
|
|
|
|
+ */
|
|
|
|
+#define TBASE_DEFERRABLE_FLAG (0x1)
|
|
|
|
+
|
|
#define TIMER_INITIALIZER(_function, _expires, _data) { \
|
|
#define TIMER_INITIALIZER(_function, _expires, _data) { \
|
|
.entry = { .prev = TIMER_ENTRY_STATIC }, \
|
|
.entry = { .prev = TIMER_ENTRY_STATIC }, \
|
|
.function = (_function), \
|
|
.function = (_function), \
|
|
@@ -59,6 +71,19 @@ extern struct tvec_base boot_tvec_bases;
|
|
__FILE__ ":" __stringify(__LINE__)) \
|
|
__FILE__ ":" __stringify(__LINE__)) \
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *) \
|
|
|
|
+ ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG))
|
|
|
|
+
|
|
|
|
+#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\
|
|
|
|
+ .entry = { .prev = TIMER_ENTRY_STATIC }, \
|
|
|
|
+ .function = (_function), \
|
|
|
|
+ .expires = (_expires), \
|
|
|
|
+ .data = (_data), \
|
|
|
|
+ .base = TBASE_MAKE_DEFERRED(&boot_tvec_bases), \
|
|
|
|
+ __TIMER_LOCKDEP_MAP_INITIALIZER( \
|
|
|
|
+ __FILE__ ":" __stringify(__LINE__)) \
|
|
|
|
+ }
|
|
|
|
+
|
|
#define DEFINE_TIMER(_name, _function, _expires, _data) \
|
|
#define DEFINE_TIMER(_name, _function, _expires, _data) \
|
|
struct timer_list _name = \
|
|
struct timer_list _name = \
|
|
TIMER_INITIALIZER(_function, _expires, _data)
|
|
TIMER_INITIALIZER(_function, _expires, _data)
|