1 From a9647655a2240148b7b6d29227dc76e9d6f12766 Mon Sep 17 00:00:00 2001
2 From: Ran Wang <ran.wang_1@nxp.com>
3 Date: Thu, 24 Oct 2019 16:36:14 +0800
4 Subject: [PATCH] PM: wakeup: Add routine to help fetch wakeup source object.
6 Some user might want to go through all registered wakeup sources
7 and doing things accordingly. For example, SoC PM driver might need to
8 do HW programming to prevent powering down specific IP which wakeup
9 source depending on. So add this API to help walk through all registered
10 wakeup source objects on that list and return them one by one.
12 Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
13 Tested-by: Leonard Crestez <leonard.crestez@nxp.com>
14 Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
15 Acked-by: Anson Huang <Anson.Huang@nxp.com>
17 drivers/base/power/wakeup.c | 54 +++++++++++++++++++++++++++++++++++++++++++++
18 include/linux/pm_wakeup.h | 9 ++++++++
19 2 files changed, 63 insertions(+)
21 --- a/drivers/base/power/wakeup.c
22 +++ b/drivers/base/power/wakeup.c
23 @@ -248,6 +248,60 @@ void wakeup_source_unregister(struct wak
24 EXPORT_SYMBOL_GPL(wakeup_source_unregister);
27 + * wakeup_sources_read_lock - Lock wakeup source list for read.
29 + * Returns an index of srcu lock for struct wakeup_srcu.
30 + * This index must be passed to the matching wakeup_sources_read_unlock().
32 +int wakeup_sources_read_lock(void)
34 + return srcu_read_lock(&wakeup_srcu);
36 +EXPORT_SYMBOL_GPL(wakeup_sources_read_lock);
39 + * wakeup_sources_read_unlock - Unlock wakeup source list.
40 + * @idx: return value from corresponding wakeup_sources_read_lock()
42 +void wakeup_sources_read_unlock(int idx)
44 + srcu_read_unlock(&wakeup_srcu, idx);
46 +EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock);
49 + * wakeup_sources_walk_start - Begin a walk on wakeup source list
51 + * Returns first object of the list of wakeup sources.
53 + * Note that to be safe, wakeup sources list needs to be locked by calling
54 + * wakeup_source_read_lock() for this.
56 +struct wakeup_source *wakeup_sources_walk_start(void)
58 + struct list_head *ws_head = &wakeup_sources;
60 + return list_entry_rcu(ws_head->next, struct wakeup_source, entry);
62 +EXPORT_SYMBOL_GPL(wakeup_sources_walk_start);
65 + * wakeup_sources_walk_next - Get next wakeup source from the list
66 + * @ws: Previous wakeup source object
68 + * Note that to be safe, wakeup sources list needs to be locked by calling
69 + * wakeup_source_read_lock() for this.
71 +struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws)
73 + struct list_head *ws_head = &wakeup_sources;
75 + return list_next_or_null_rcu(ws_head, &ws->entry,
76 + struct wakeup_source, entry);
78 +EXPORT_SYMBOL_GPL(wakeup_sources_walk_next);
81 * device_wakeup_attach - Attach a wakeup source object to a device object.
82 * @dev: Device to handle.
83 * @ws: Wakeup source object to attach to @dev.
84 --- a/include/linux/pm_wakeup.h
85 +++ b/include/linux/pm_wakeup.h
86 @@ -63,6 +63,11 @@ struct wakeup_source {
87 bool autosleep_enabled:1;
90 +#define for_each_wakeup_source(ws) \
91 + for ((ws) = wakeup_sources_walk_start(); \
93 + (ws) = wakeup_sources_walk_next((ws)))
95 #ifdef CONFIG_PM_SLEEP
98 @@ -92,6 +97,10 @@ extern void wakeup_source_remove(struct
99 extern struct wakeup_source *wakeup_source_register(struct device *dev,
101 extern void wakeup_source_unregister(struct wakeup_source *ws);
102 +extern int wakeup_sources_read_lock(void);
103 +extern void wakeup_sources_read_unlock(int idx);
104 +extern struct wakeup_source *wakeup_sources_walk_start(void);
105 +extern struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws);
106 extern int device_wakeup_enable(struct device *dev);
107 extern int device_wakeup_disable(struct device *dev);
108 extern void device_set_wakeup_capable(struct device *dev, bool capable);