42514bbc4a5d060aa97d2e191f0d5f358fcbe7b0
[oweals/openwrt.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 @@ -248,6 +248,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);