diff options
-rw-r--r-- | drivers/base/power/wakeup.c | 50 | ||||
-rw-r--r-- | include/linux/pm_wakeup.h | 22 |
2 files changed, 62 insertions, 10 deletions
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 7c5ab70b9ef3..2a3e581b8dcd 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -53,6 +53,23 @@ static void pm_wakeup_timer_fn(unsigned long data); | |||
53 | static LIST_HEAD(wakeup_sources); | 53 | static LIST_HEAD(wakeup_sources); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * wakeup_source_prepare - Prepare a new wakeup source for initialization. | ||
57 | * @ws: Wakeup source to prepare. | ||
58 | * @name: Pointer to the name of the new wakeup source. | ||
59 | * | ||
60 | * Callers must ensure that the @name string won't be freed when @ws is still in | ||
61 | * use. | ||
62 | */ | ||
63 | void wakeup_source_prepare(struct wakeup_source *ws, const char *name) | ||
64 | { | ||
65 | if (ws) { | ||
66 | memset(ws, 0, sizeof(*ws)); | ||
67 | ws->name = name; | ||
68 | } | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(wakeup_source_prepare); | ||
71 | |||
72 | /** | ||
56 | * wakeup_source_create - Create a struct wakeup_source object. | 73 | * wakeup_source_create - Create a struct wakeup_source object. |
57 | * @name: Name of the new wakeup source. | 74 | * @name: Name of the new wakeup source. |
58 | */ | 75 | */ |
@@ -60,31 +77,44 @@ struct wakeup_source *wakeup_source_create(const char *name) | |||
60 | { | 77 | { |
61 | struct wakeup_source *ws; | 78 | struct wakeup_source *ws; |
62 | 79 | ||
63 | ws = kzalloc(sizeof(*ws), GFP_KERNEL); | 80 | ws = kmalloc(sizeof(*ws), GFP_KERNEL); |
64 | if (!ws) | 81 | if (!ws) |
65 | return NULL; | 82 | return NULL; |
66 | 83 | ||
67 | if (name) | 84 | wakeup_source_prepare(ws, name ? kstrdup(name, GFP_KERNEL) : NULL); |
68 | ws->name = kstrdup(name, GFP_KERNEL); | ||
69 | |||
70 | return ws; | 85 | return ws; |
71 | } | 86 | } |
72 | EXPORT_SYMBOL_GPL(wakeup_source_create); | 87 | EXPORT_SYMBOL_GPL(wakeup_source_create); |
73 | 88 | ||
74 | /** | 89 | /** |
75 | * wakeup_source_destroy - Destroy a struct wakeup_source object. | 90 | * wakeup_source_drop - Prepare a struct wakeup_source object for destruction. |
76 | * @ws: Wakeup source to destroy. | 91 | * @ws: Wakeup source to prepare for destruction. |
77 | * | 92 | * |
78 | * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never | 93 | * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never |
79 | * be run in parallel with this function for the same wakeup source object. | 94 | * be run in parallel with this function for the same wakeup source object. |
80 | */ | 95 | */ |
81 | void wakeup_source_destroy(struct wakeup_source *ws) | 96 | void wakeup_source_drop(struct wakeup_source *ws) |
82 | { | 97 | { |
83 | if (!ws) | 98 | if (!ws) |
84 | return; | 99 | return; |
85 | 100 | ||
86 | del_timer_sync(&ws->timer); | 101 | del_timer_sync(&ws->timer); |
87 | __pm_relax(ws); | 102 | __pm_relax(ws); |
103 | } | ||
104 | EXPORT_SYMBOL_GPL(wakeup_source_drop); | ||
105 | |||
106 | /** | ||
107 | * wakeup_source_destroy - Destroy a struct wakeup_source object. | ||
108 | * @ws: Wakeup source to destroy. | ||
109 | * | ||
110 | * Use only for wakeup source objects created with wakeup_source_create(). | ||
111 | */ | ||
112 | void wakeup_source_destroy(struct wakeup_source *ws) | ||
113 | { | ||
114 | if (!ws) | ||
115 | return; | ||
116 | |||
117 | wakeup_source_drop(ws); | ||
88 | kfree(ws->name); | 118 | kfree(ws->name); |
89 | kfree(ws); | 119 | kfree(ws); |
90 | } | 120 | } |
@@ -147,8 +177,10 @@ EXPORT_SYMBOL_GPL(wakeup_source_register); | |||
147 | */ | 177 | */ |
148 | void wakeup_source_unregister(struct wakeup_source *ws) | 178 | void wakeup_source_unregister(struct wakeup_source *ws) |
149 | { | 179 | { |
150 | wakeup_source_remove(ws); | 180 | if (ws) { |
151 | wakeup_source_destroy(ws); | 181 | wakeup_source_remove(ws); |
182 | wakeup_source_destroy(ws); | ||
183 | } | ||
152 | } | 184 | } |
153 | EXPORT_SYMBOL_GPL(wakeup_source_unregister); | 185 | EXPORT_SYMBOL_GPL(wakeup_source_unregister); |
154 | 186 | ||
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index a32da962d693..d9f05113e5fb 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h | |||
@@ -41,7 +41,7 @@ | |||
41 | * @active: Status of the wakeup source. | 41 | * @active: Status of the wakeup source. |
42 | */ | 42 | */ |
43 | struct wakeup_source { | 43 | struct wakeup_source { |
44 | char *name; | 44 | const char *name; |
45 | struct list_head entry; | 45 | struct list_head entry; |
46 | spinlock_t lock; | 46 | spinlock_t lock; |
47 | struct timer_list timer; | 47 | struct timer_list timer; |
@@ -73,7 +73,9 @@ static inline bool device_may_wakeup(struct device *dev) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /* drivers/base/power/wakeup.c */ | 75 | /* drivers/base/power/wakeup.c */ |
76 | extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name); | ||
76 | extern struct wakeup_source *wakeup_source_create(const char *name); | 77 | extern struct wakeup_source *wakeup_source_create(const char *name); |
78 | extern void wakeup_source_drop(struct wakeup_source *ws); | ||
77 | extern void wakeup_source_destroy(struct wakeup_source *ws); | 79 | extern void wakeup_source_destroy(struct wakeup_source *ws); |
78 | extern void wakeup_source_add(struct wakeup_source *ws); | 80 | extern void wakeup_source_add(struct wakeup_source *ws); |
79 | extern void wakeup_source_remove(struct wakeup_source *ws); | 81 | extern void wakeup_source_remove(struct wakeup_source *ws); |
@@ -103,11 +105,16 @@ static inline bool device_can_wakeup(struct device *dev) | |||
103 | return dev->power.can_wakeup; | 105 | return dev->power.can_wakeup; |
104 | } | 106 | } |
105 | 107 | ||
108 | static inline void wakeup_source_prepare(struct wakeup_source *ws, | ||
109 | const char *name) {} | ||
110 | |||
106 | static inline struct wakeup_source *wakeup_source_create(const char *name) | 111 | static inline struct wakeup_source *wakeup_source_create(const char *name) |
107 | { | 112 | { |
108 | return NULL; | 113 | return NULL; |
109 | } | 114 | } |
110 | 115 | ||
116 | static inline void wakeup_source_drop(struct wakeup_source *ws) {} | ||
117 | |||
111 | static inline void wakeup_source_destroy(struct wakeup_source *ws) {} | 118 | static inline void wakeup_source_destroy(struct wakeup_source *ws) {} |
112 | 119 | ||
113 | static inline void wakeup_source_add(struct wakeup_source *ws) {} | 120 | static inline void wakeup_source_add(struct wakeup_source *ws) {} |
@@ -165,4 +172,17 @@ static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {} | |||
165 | 172 | ||
166 | #endif /* !CONFIG_PM_SLEEP */ | 173 | #endif /* !CONFIG_PM_SLEEP */ |
167 | 174 | ||
175 | static inline void wakeup_source_init(struct wakeup_source *ws, | ||
176 | const char *name) | ||
177 | { | ||
178 | wakeup_source_prepare(ws, name); | ||
179 | wakeup_source_add(ws); | ||
180 | } | ||
181 | |||
182 | static inline void wakeup_source_trash(struct wakeup_source *ws) | ||
183 | { | ||
184 | wakeup_source_remove(ws); | ||
185 | wakeup_source_drop(ws); | ||
186 | } | ||
187 | |||
168 | #endif /* _LINUX_PM_WAKEUP_H */ | 188 | #endif /* _LINUX_PM_WAKEUP_H */ |