diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-17 14:25:33 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-17 14:25:33 -0400 |
commit | 079d364b042afbe811c4bb0cb57fcbf4f1cfab6d (patch) | |
tree | e31d0b06bc05cfe5bdabb30c8249489226153860 | |
parent | 8592013bbd3858e9427ea2c5fb23a2c983b4dcaa (diff) | |
parent | b3d3b9fb6016e6eacd3ae49fb786806d00c43e7b (diff) |
Merge branch 'pm-domains'
* pm-domains:
PM / Domains: Fix compilation warning related to genpd_start_dev_no_timing()
PM / Domains: Operations related to cpuidle using domain names
PM / Domains: Document cpuidle-related functions and change their names
PM / Domains: Add power-on function using names to identify domains
PM / Domains: Make it possible to use names when adding subdomains
PM / Domains: Make it possible to use domain names when adding devices
-rw-r--r-- | drivers/base/power/domain.c | 126 | ||||
-rw-r--r-- | include/linux/pm_domain.h | 73 |
2 files changed, 173 insertions, 26 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5f4606f13be6..c22b869245d9 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -53,6 +53,24 @@ | |||
53 | static LIST_HEAD(gpd_list); | 53 | static LIST_HEAD(gpd_list); |
54 | static DEFINE_MUTEX(gpd_list_lock); | 54 | static DEFINE_MUTEX(gpd_list_lock); |
55 | 55 | ||
56 | static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) | ||
57 | { | ||
58 | struct generic_pm_domain *genpd = NULL, *gpd; | ||
59 | |||
60 | if (IS_ERR_OR_NULL(domain_name)) | ||
61 | return NULL; | ||
62 | |||
63 | mutex_lock(&gpd_list_lock); | ||
64 | list_for_each_entry(gpd, &gpd_list, gpd_list_node) { | ||
65 | if (!strcmp(gpd->name, domain_name)) { | ||
66 | genpd = gpd; | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | mutex_unlock(&gpd_list_lock); | ||
71 | return genpd; | ||
72 | } | ||
73 | |||
56 | #ifdef CONFIG_PM | 74 | #ifdef CONFIG_PM |
57 | 75 | ||
58 | struct generic_pm_domain *dev_to_genpd(struct device *dev) | 76 | struct generic_pm_domain *dev_to_genpd(struct device *dev) |
@@ -75,12 +93,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev) | |||
75 | start_latency_ns, "start"); | 93 | start_latency_ns, "start"); |
76 | } | 94 | } |
77 | 95 | ||
78 | static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd, | ||
79 | struct device *dev) | ||
80 | { | ||
81 | return GENPD_DEV_CALLBACK(genpd, int, start, dev); | ||
82 | } | ||
83 | |||
84 | static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) | 96 | static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) |
85 | { | 97 | { |
86 | bool ret = false; | 98 | bool ret = false; |
@@ -262,10 +274,28 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd) | |||
262 | return ret; | 274 | return ret; |
263 | } | 275 | } |
264 | 276 | ||
277 | /** | ||
278 | * pm_genpd_name_poweron - Restore power to a given PM domain and its masters. | ||
279 | * @domain_name: Name of the PM domain to power up. | ||
280 | */ | ||
281 | int pm_genpd_name_poweron(const char *domain_name) | ||
282 | { | ||
283 | struct generic_pm_domain *genpd; | ||
284 | |||
285 | genpd = pm_genpd_lookup_name(domain_name); | ||
286 | return genpd ? pm_genpd_poweron(genpd) : -EINVAL; | ||
287 | } | ||
288 | |||
265 | #endif /* CONFIG_PM */ | 289 | #endif /* CONFIG_PM */ |
266 | 290 | ||
267 | #ifdef CONFIG_PM_RUNTIME | 291 | #ifdef CONFIG_PM_RUNTIME |
268 | 292 | ||
293 | static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd, | ||
294 | struct device *dev) | ||
295 | { | ||
296 | return GENPD_DEV_CALLBACK(genpd, int, start, dev); | ||
297 | } | ||
298 | |||
269 | static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) | 299 | static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) |
270 | { | 300 | { |
271 | return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev, | 301 | return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev, |
@@ -1465,6 +1495,19 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev, | |||
1465 | return __pm_genpd_add_device(genpd, dev, td); | 1495 | return __pm_genpd_add_device(genpd, dev, td); |
1466 | } | 1496 | } |
1467 | 1497 | ||
1498 | |||
1499 | /** | ||
1500 | * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it. | ||
1501 | * @domain_name: Name of the PM domain to add the device to. | ||
1502 | * @dev: Device to be added. | ||
1503 | * @td: Set of PM QoS timing parameters to attach to the device. | ||
1504 | */ | ||
1505 | int __pm_genpd_name_add_device(const char *domain_name, struct device *dev, | ||
1506 | struct gpd_timing_data *td) | ||
1507 | { | ||
1508 | return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td); | ||
1509 | } | ||
1510 | |||
1468 | /** | 1511 | /** |
1469 | * pm_genpd_remove_device - Remove a device from an I/O PM domain. | 1512 | * pm_genpd_remove_device - Remove a device from an I/O PM domain. |
1470 | * @genpd: PM domain to remove the device from. | 1513 | * @genpd: PM domain to remove the device from. |
@@ -1557,7 +1600,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, | |||
1557 | struct gpd_link *link; | 1600 | struct gpd_link *link; |
1558 | int ret = 0; | 1601 | int ret = 0; |
1559 | 1602 | ||
1560 | if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) | 1603 | if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain) |
1604 | || genpd == subdomain) | ||
1561 | return -EINVAL; | 1605 | return -EINVAL; |
1562 | 1606 | ||
1563 | start: | 1607 | start: |
@@ -1604,6 +1648,35 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, | |||
1604 | } | 1648 | } |
1605 | 1649 | ||
1606 | /** | 1650 | /** |
1651 | * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain. | ||
1652 | * @master_name: Name of the master PM domain to add the subdomain to. | ||
1653 | * @subdomain_name: Name of the subdomain to be added. | ||
1654 | */ | ||
1655 | int pm_genpd_add_subdomain_names(const char *master_name, | ||
1656 | const char *subdomain_name) | ||
1657 | { | ||
1658 | struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd; | ||
1659 | |||
1660 | if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name)) | ||
1661 | return -EINVAL; | ||
1662 | |||
1663 | mutex_lock(&gpd_list_lock); | ||
1664 | list_for_each_entry(gpd, &gpd_list, gpd_list_node) { | ||
1665 | if (!master && !strcmp(gpd->name, master_name)) | ||
1666 | master = gpd; | ||
1667 | |||
1668 | if (!subdomain && !strcmp(gpd->name, subdomain_name)) | ||
1669 | subdomain = gpd; | ||
1670 | |||
1671 | if (master && subdomain) | ||
1672 | break; | ||
1673 | } | ||
1674 | mutex_unlock(&gpd_list_lock); | ||
1675 | |||
1676 | return pm_genpd_add_subdomain(master, subdomain); | ||
1677 | } | ||
1678 | |||
1679 | /** | ||
1607 | * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. | 1680 | * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. |
1608 | * @genpd: Master PM domain to remove the subdomain from. | 1681 | * @genpd: Master PM domain to remove the subdomain from. |
1609 | * @subdomain: Subdomain to be removed. | 1682 | * @subdomain: Subdomain to be removed. |
@@ -1756,7 +1829,16 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td) | |||
1756 | } | 1829 | } |
1757 | EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks); | 1830 | EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks); |
1758 | 1831 | ||
1759 | int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) | 1832 | /** |
1833 | * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle. | ||
1834 | * @genpd: PM domain to be connected with cpuidle. | ||
1835 | * @state: cpuidle state this domain can disable/enable. | ||
1836 | * | ||
1837 | * Make a PM domain behave as though it contained a CPU core, that is, instead | ||
1838 | * of calling its power down routine it will enable the given cpuidle state so | ||
1839 | * that the cpuidle subsystem can power it down (if possible and desirable). | ||
1840 | */ | ||
1841 | int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) | ||
1760 | { | 1842 | { |
1761 | struct cpuidle_driver *cpuidle_drv; | 1843 | struct cpuidle_driver *cpuidle_drv; |
1762 | struct gpd_cpu_data *cpu_data; | 1844 | struct gpd_cpu_data *cpu_data; |
@@ -1805,7 +1887,24 @@ int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) | |||
1805 | goto out; | 1887 | goto out; |
1806 | } | 1888 | } |
1807 | 1889 | ||
1808 | int genpd_detach_cpuidle(struct generic_pm_domain *genpd) | 1890 | /** |
1891 | * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it. | ||
1892 | * @name: Name of the domain to connect to cpuidle. | ||
1893 | * @state: cpuidle state this domain can manipulate. | ||
1894 | */ | ||
1895 | int pm_genpd_name_attach_cpuidle(const char *name, int state) | ||
1896 | { | ||
1897 | return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state); | ||
1898 | } | ||
1899 | |||
1900 | /** | ||
1901 | * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain. | ||
1902 | * @genpd: PM domain to remove the cpuidle connection from. | ||
1903 | * | ||
1904 | * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the | ||
1905 | * given PM domain. | ||
1906 | */ | ||
1907 | int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) | ||
1809 | { | 1908 | { |
1810 | struct gpd_cpu_data *cpu_data; | 1909 | struct gpd_cpu_data *cpu_data; |
1811 | struct cpuidle_state *idle_state; | 1910 | struct cpuidle_state *idle_state; |
@@ -1836,6 +1935,15 @@ int genpd_detach_cpuidle(struct generic_pm_domain *genpd) | |||
1836 | return ret; | 1935 | return ret; |
1837 | } | 1936 | } |
1838 | 1937 | ||
1938 | /** | ||
1939 | * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it. | ||
1940 | * @name: Name of the domain to disconnect cpuidle from. | ||
1941 | */ | ||
1942 | int pm_genpd_name_detach_cpuidle(const char *name) | ||
1943 | { | ||
1944 | return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name)); | ||
1945 | } | ||
1946 | |||
1839 | /* Default device callbacks for generic PM domains. */ | 1947 | /* Default device callbacks for generic PM domains. */ |
1840 | 1948 | ||
1841 | /** | 1949 | /** |
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 08adf8e5a80e..7c1d252b20c0 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h | |||
@@ -138,35 +138,32 @@ extern int __pm_genpd_of_add_device(struct device_node *genpd_node, | |||
138 | struct device *dev, | 138 | struct device *dev, |
139 | struct gpd_timing_data *td); | 139 | struct gpd_timing_data *td); |
140 | 140 | ||
141 | static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, | 141 | extern int __pm_genpd_name_add_device(const char *domain_name, |
142 | struct device *dev) | 142 | struct device *dev, |
143 | { | 143 | struct gpd_timing_data *td); |
144 | return __pm_genpd_add_device(genpd, dev, NULL); | ||
145 | } | ||
146 | |||
147 | static inline int pm_genpd_of_add_device(struct device_node *genpd_node, | ||
148 | struct device *dev) | ||
149 | { | ||
150 | return __pm_genpd_of_add_device(genpd_node, dev, NULL); | ||
151 | } | ||
152 | 144 | ||
153 | extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, | 145 | extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, |
154 | struct device *dev); | 146 | struct device *dev); |
155 | extern void pm_genpd_dev_need_restore(struct device *dev, bool val); | 147 | extern void pm_genpd_dev_need_restore(struct device *dev, bool val); |
156 | extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, | 148 | extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, |
157 | struct generic_pm_domain *new_subdomain); | 149 | struct generic_pm_domain *new_subdomain); |
150 | extern int pm_genpd_add_subdomain_names(const char *master_name, | ||
151 | const char *subdomain_name); | ||
158 | extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, | 152 | extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, |
159 | struct generic_pm_domain *target); | 153 | struct generic_pm_domain *target); |
160 | extern int pm_genpd_add_callbacks(struct device *dev, | 154 | extern int pm_genpd_add_callbacks(struct device *dev, |
161 | struct gpd_dev_ops *ops, | 155 | struct gpd_dev_ops *ops, |
162 | struct gpd_timing_data *td); | 156 | struct gpd_timing_data *td); |
163 | extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td); | 157 | extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td); |
164 | extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state); | 158 | extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state); |
165 | extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd); | 159 | extern int pm_genpd_name_attach_cpuidle(const char *name, int state); |
160 | extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd); | ||
161 | extern int pm_genpd_name_detach_cpuidle(const char *name); | ||
166 | extern void pm_genpd_init(struct generic_pm_domain *genpd, | 162 | extern void pm_genpd_init(struct generic_pm_domain *genpd, |
167 | struct dev_power_governor *gov, bool is_off); | 163 | struct dev_power_governor *gov, bool is_off); |
168 | 164 | ||
169 | extern int pm_genpd_poweron(struct generic_pm_domain *genpd); | 165 | extern int pm_genpd_poweron(struct generic_pm_domain *genpd); |
166 | extern int pm_genpd_name_poweron(const char *domain_name); | ||
170 | 167 | ||
171 | extern bool default_stop_ok(struct device *dev); | 168 | extern bool default_stop_ok(struct device *dev); |
172 | 169 | ||
@@ -187,8 +184,15 @@ static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd, | |||
187 | { | 184 | { |
188 | return -ENOSYS; | 185 | return -ENOSYS; |
189 | } | 186 | } |
190 | static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, | 187 | static inline int __pm_genpd_of_add_device(struct device_node *genpd_node, |
191 | struct device *dev) | 188 | struct device *dev, |
189 | struct gpd_timing_data *td) | ||
190 | { | ||
191 | return -ENOSYS; | ||
192 | } | ||
193 | static inline int __pm_genpd_name_add_device(const char *domain_name, | ||
194 | struct device *dev, | ||
195 | struct gpd_timing_data *td) | ||
192 | { | 196 | { |
193 | return -ENOSYS; | 197 | return -ENOSYS; |
194 | } | 198 | } |
@@ -203,6 +207,11 @@ static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, | |||
203 | { | 207 | { |
204 | return -ENOSYS; | 208 | return -ENOSYS; |
205 | } | 209 | } |
210 | static inline int pm_genpd_add_subdomain_names(const char *master_name, | ||
211 | const char *subdomain_name) | ||
212 | { | ||
213 | return -ENOSYS; | ||
214 | } | ||
206 | static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, | 215 | static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, |
207 | struct generic_pm_domain *target) | 216 | struct generic_pm_domain *target) |
208 | { | 217 | { |
@@ -218,11 +227,19 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td) | |||
218 | { | 227 | { |
219 | return -ENOSYS; | 228 | return -ENOSYS; |
220 | } | 229 | } |
221 | static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st) | 230 | static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st) |
231 | { | ||
232 | return -ENOSYS; | ||
233 | } | ||
234 | static inline int pm_genpd_name_attach_cpuidle(const char *name, int state) | ||
222 | { | 235 | { |
223 | return -ENOSYS; | 236 | return -ENOSYS; |
224 | } | 237 | } |
225 | static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd) | 238 | static inline int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) |
239 | { | ||
240 | return -ENOSYS; | ||
241 | } | ||
242 | static inline int pm_genpd_name_detach_cpuidle(const char *name) | ||
226 | { | 243 | { |
227 | return -ENOSYS; | 244 | return -ENOSYS; |
228 | } | 245 | } |
@@ -234,6 +251,10 @@ static inline int pm_genpd_poweron(struct generic_pm_domain *genpd) | |||
234 | { | 251 | { |
235 | return -ENOSYS; | 252 | return -ENOSYS; |
236 | } | 253 | } |
254 | static inline int pm_genpd_name_poweron(const char *domain_name) | ||
255 | { | ||
256 | return -ENOSYS; | ||
257 | } | ||
237 | static inline bool default_stop_ok(struct device *dev) | 258 | static inline bool default_stop_ok(struct device *dev) |
238 | { | 259 | { |
239 | return false; | 260 | return false; |
@@ -242,6 +263,24 @@ static inline bool default_stop_ok(struct device *dev) | |||
242 | #define pm_domain_always_on_gov NULL | 263 | #define pm_domain_always_on_gov NULL |
243 | #endif | 264 | #endif |
244 | 265 | ||
266 | static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, | ||
267 | struct device *dev) | ||
268 | { | ||
269 | return __pm_genpd_add_device(genpd, dev, NULL); | ||
270 | } | ||
271 | |||
272 | static inline int pm_genpd_of_add_device(struct device_node *genpd_node, | ||
273 | struct device *dev) | ||
274 | { | ||
275 | return __pm_genpd_of_add_device(genpd_node, dev, NULL); | ||
276 | } | ||
277 | |||
278 | static inline int pm_genpd_name_add_device(const char *domain_name, | ||
279 | struct device *dev) | ||
280 | { | ||
281 | return __pm_genpd_name_add_device(domain_name, dev, NULL); | ||
282 | } | ||
283 | |||
245 | static inline int pm_genpd_remove_callbacks(struct device *dev) | 284 | static inline int pm_genpd_remove_callbacks(struct device *dev) |
246 | { | 285 | { |
247 | return __pm_genpd_remove_callbacks(dev, true); | 286 | return __pm_genpd_remove_callbacks(dev, true); |