091588b1d79ee14456462936e4ad5d97dcccb454
[openwrt/staging/blocktrron.git] /
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.
5
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.
11
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>
16 ---
17 drivers/base/power/wakeup.c | 54 +++++++++++++++++++++++++++++++++++++++++++++
18 include/linux/pm_wakeup.h | 9 ++++++++
19 2 files changed, 63 insertions(+)
20
21 --- a/drivers/base/power/wakeup.c
22 +++ b/drivers/base/power/wakeup.c
23 @@ -250,6 +250,60 @@ void wakeup_source_unregister(struct wak
24 EXPORT_SYMBOL_GPL(wakeup_source_unregister);
25
26 /**
27 + * wakeup_sources_read_lock - Lock wakeup source list for read.
28 + *
29 + * Returns an index of srcu lock for struct wakeup_srcu.
30 + * This index must be passed to the matching wakeup_sources_read_unlock().
31 + */
32 +int wakeup_sources_read_lock(void)
33 +{
34 + return srcu_read_lock(&wakeup_srcu);
35 +}
36 +EXPORT_SYMBOL_GPL(wakeup_sources_read_lock);
37 +
38 +/**
39 + * wakeup_sources_read_unlock - Unlock wakeup source list.
40 + * @idx: return value from corresponding wakeup_sources_read_lock()
41 + */
42 +void wakeup_sources_read_unlock(int idx)
43 +{
44 + srcu_read_unlock(&wakeup_srcu, idx);
45 +}
46 +EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock);
47 +
48 +/**
49 + * wakeup_sources_walk_start - Begin a walk on wakeup source list
50 + *
51 + * Returns first object of the list of wakeup sources.
52 + *
53 + * Note that to be safe, wakeup sources list needs to be locked by calling
54 + * wakeup_source_read_lock() for this.
55 + */
56 +struct wakeup_source *wakeup_sources_walk_start(void)
57 +{
58 + struct list_head *ws_head = &wakeup_sources;
59 +
60 + return list_entry_rcu(ws_head->next, struct wakeup_source, entry);
61 +}
62 +EXPORT_SYMBOL_GPL(wakeup_sources_walk_start);
63 +
64 +/**
65 + * wakeup_sources_walk_next - Get next wakeup source from the list
66 + * @ws: Previous wakeup source object
67 + *
68 + * Note that to be safe, wakeup sources list needs to be locked by calling
69 + * wakeup_source_read_lock() for this.
70 + */
71 +struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws)
72 +{
73 + struct list_head *ws_head = &wakeup_sources;
74 +
75 + return list_next_or_null_rcu(ws_head, &ws->entry,
76 + struct wakeup_source, entry);
77 +}
78 +EXPORT_SYMBOL_GPL(wakeup_sources_walk_next);
79 +
80 +/**
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;
88 };
89
90 +#define for_each_wakeup_source(ws) \
91 + for ((ws) = wakeup_sources_walk_start(); \
92 + (ws); \
93 + (ws) = wakeup_sources_walk_next((ws)))
94 +
95 #ifdef CONFIG_PM_SLEEP
96
97 /*
98 @@ -92,6 +97,10 @@ extern void wakeup_source_remove(struct
99 extern struct wakeup_source *wakeup_source_register(struct device *dev,
100 const char *name);
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);