Commit 8671bbc1bd0442ef0eab27f7d56216431c490820

Authored by Rafael J. Wysocki
1 parent 05b4877f6a

PM / Sleep: Add more wakeup source initialization routines

The existing wakeup source initialization routines are not
particularly useful for wakeup sources that aren't created by
wakeup_source_create(), because their users have to open code
filling the objects with zeros and setting their names.  For this
reason, introduce routines that can be used for initializing, for
example, static wakeup source objects.

Requested-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Showing 2 changed files with 62 additions and 10 deletions Side-by-side Diff

drivers/base/power/wakeup.c
... ... @@ -53,6 +53,23 @@
53 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 73 * wakeup_source_create - Create a struct wakeup_source object.
57 74 * @name: Name of the new wakeup source.
58 75 */
59 76  
60 77  
61 78  
62 79  
... ... @@ -60,31 +77,44 @@
60 77 {
61 78 struct wakeup_source *ws;
62 79  
63   - ws = kzalloc(sizeof(*ws), GFP_KERNEL);
  80 + ws = kmalloc(sizeof(*ws), GFP_KERNEL);
64 81 if (!ws)
65 82 return NULL;
66 83  
67   - if (name)
68   - ws->name = kstrdup(name, GFP_KERNEL);
69   -
  84 + wakeup_source_prepare(ws, name ? kstrdup(name, GFP_KERNEL) : NULL);
70 85 return ws;
71 86 }
72 87 EXPORT_SYMBOL_GPL(wakeup_source_create);
73 88  
74 89 /**
75   - * wakeup_source_destroy - Destroy a struct wakeup_source object.
76   - * @ws: Wakeup source to destroy.
  90 + * wakeup_source_drop - Prepare a struct wakeup_source object for destruction.
  91 + * @ws: Wakeup source to prepare for destruction.
77 92 *
78 93 * Callers must ensure that __pm_stay_awake() or __pm_wakeup_event() will never
79 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 98 if (!ws)
84 99 return;
85 100  
86 101 del_timer_sync(&ws->timer);
87 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 118 kfree(ws->name);
89 119 kfree(ws);
90 120 }
... ... @@ -147,8 +177,10 @@
147 177 */
148 178 void wakeup_source_unregister(struct wakeup_source *ws)
149 179 {
150   - wakeup_source_remove(ws);
151   - wakeup_source_destroy(ws);
  180 + if (ws) {
  181 + wakeup_source_remove(ws);
  182 + wakeup_source_destroy(ws);
  183 + }
152 184 }
153 185 EXPORT_SYMBOL_GPL(wakeup_source_unregister);
154 186  
include/linux/pm_wakeup.h
... ... @@ -41,7 +41,7 @@
41 41 * @active: Status of the wakeup source.
42 42 */
43 43 struct wakeup_source {
44   - char *name;
  44 + const char *name;
45 45 struct list_head entry;
46 46 spinlock_t lock;
47 47 struct timer_list timer;
48 48  
... ... @@ -73,7 +73,9 @@
73 73 }
74 74  
75 75 /* drivers/base/power/wakeup.c */
  76 +extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name);
76 77 extern struct wakeup_source *wakeup_source_create(const char *name);
  78 +extern void wakeup_source_drop(struct wakeup_source *ws);
77 79 extern void wakeup_source_destroy(struct wakeup_source *ws);
78 80 extern void wakeup_source_add(struct wakeup_source *ws);
79 81 extern void wakeup_source_remove(struct wakeup_source *ws);
80 82  
... ... @@ -103,11 +105,16 @@
103 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 111 static inline struct wakeup_source *wakeup_source_create(const char *name)
107 112 {
108 113 return NULL;
109 114 }
110 115  
  116 +static inline void wakeup_source_drop(struct wakeup_source *ws) {}
  117 +
111 118 static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
112 119  
113 120 static inline void wakeup_source_add(struct wakeup_source *ws) {}
... ... @@ -164,6 +171,19 @@
164 171 static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
165 172  
166 173 #endif /* !CONFIG_PM_SLEEP */
  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 +}
167 187  
168 188 #endif /* _LINUX_PM_WAKEUP_H */