aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-09-26 14:12:45 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-09-26 14:12:45 -0400
commit0d41da2e31e81f5c8aaabe17f769de4304b2d4c8 (patch)
tree540acefba9bf01d3880d7bacb767fbf9b1fe80b4 /drivers/base
parenta0089bd617adea27ebc352e1e0871649ab1dbaa6 (diff)
parente8b364b88cc4001b21c28c1ecf1e1e3ffbe162e6 (diff)
Merge branch 'pm-fixes' into pm-domains
Merge commit e8b364b88cc4001b21c28c1ecf1e1e3ffbe162e6 (PM / Clocks: Do not acquire a mutex under a spinlock) fixing a regression in drivers/base/power/clock_ops.c. Conflicts: drivers/base/power/clock_ops.c
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/devres.c1
-rw-r--r--drivers/base/devtmpfs.c2
-rw-r--r--drivers/base/firmware_class.c11
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power/clock_ops.c76
-rw-r--r--drivers/base/regmap/regmap.c5
6 files changed, 49 insertions, 48 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index cf7a0c78805..65cd7483245 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -397,6 +397,7 @@ static int remove_nodes(struct device *dev,
397 397
398static int release_nodes(struct device *dev, struct list_head *first, 398static int release_nodes(struct device *dev, struct list_head *first,
399 struct list_head *end, unsigned long flags) 399 struct list_head *end, unsigned long flags)
400 __releases(&dev->devres_lock)
400{ 401{
401 LIST_HEAD(todo); 402 LIST_HEAD(todo);
402 int cnt; 403 int cnt;
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 33e1bed68fd..a4760e095ff 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -376,7 +376,7 @@ int devtmpfs_mount(const char *mntdir)
376 return err; 376 return err;
377} 377}
378 378
379static __initdata DECLARE_COMPLETION(setup_done); 379static DECLARE_COMPLETION(setup_done);
380 380
381static int handle(const char *name, mode_t mode, struct device *dev) 381static int handle(const char *name, mode_t mode, struct device *dev)
382{ 382{
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index bbb03e6f725..06ed6b4e7df 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -521,11 +521,6 @@ static int _request_firmware(const struct firmware **firmware_p,
521 if (!firmware_p) 521 if (!firmware_p)
522 return -EINVAL; 522 return -EINVAL;
523 523
524 if (WARN_ON(usermodehelper_is_disabled())) {
525 dev_err(device, "firmware: %s will not be loaded\n", name);
526 return -EBUSY;
527 }
528
529 *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); 524 *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
530 if (!firmware) { 525 if (!firmware) {
531 dev_err(device, "%s: kmalloc(struct firmware) failed\n", 526 dev_err(device, "%s: kmalloc(struct firmware) failed\n",
@@ -539,6 +534,12 @@ static int _request_firmware(const struct firmware **firmware_p,
539 return 0; 534 return 0;
540 } 535 }
541 536
537 if (WARN_ON(usermodehelper_is_disabled())) {
538 dev_err(device, "firmware: %s will not be loaded\n", name);
539 retval = -EBUSY;
540 goto out;
541 }
542
542 if (uevent) 543 if (uevent)
543 dev_dbg(device, "firmware: requesting %s\n", name); 544 dev_dbg(device, "firmware: requesting %s\n", name);
544 545
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 0cad9c7f6bb..99a5272d7c2 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
33 33
34/** 34/**
35 * arch_setup_pdev_archdata - Allow manipulation of archdata before its used 35 * arch_setup_pdev_archdata - Allow manipulation of archdata before its used
36 * @dev: platform device 36 * @pdev: platform device
37 * 37 *
38 * This is called before platform_device_add() such that any pdev_archdata may 38 * This is called before platform_device_add() such that any pdev_archdata may
39 * be setup before the platform_notifier is called. So if a user needs to 39 * be setup before the platform_notifier is called. So if a user needs to
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index cb44b58d681..b876e60a53e 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -32,6 +32,22 @@ struct pm_clock_entry {
32}; 32};
33 33
34/** 34/**
35 * pm_clk_acquire - Acquire a device clock.
36 * @dev: Device whose clock is to be acquired.
37 * @ce: PM clock entry corresponding to the clock.
38 */
39static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
40{
41 ce->clk = clk_get(dev, ce->con_id);
42 if (IS_ERR(ce->clk)) {
43 ce->status = PCE_STATUS_ERROR;
44 } else {
45 ce->status = PCE_STATUS_ACQUIRED;
46 dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
47 }
48}
49
50/**
35 * pm_clk_add - Start using a device clock for power management. 51 * pm_clk_add - Start using a device clock for power management.
36 * @dev: Device whose clock is going to be used for power management. 52 * @dev: Device whose clock is going to be used for power management.
37 * @con_id: Connection ID of the clock. 53 * @con_id: Connection ID of the clock.
@@ -63,6 +79,8 @@ int pm_clk_add(struct device *dev, const char *con_id)
63 } 79 }
64 } 80 }
65 81
82 pm_clk_acquire(dev, ce);
83
66 spin_lock_irq(&psd->lock); 84 spin_lock_irq(&psd->lock);
67 list_add_tail(&ce->node, &psd->clock_list); 85 list_add_tail(&ce->node, &psd->clock_list);
68 spin_unlock_irq(&psd->lock); 86 spin_unlock_irq(&psd->lock);
@@ -72,17 +90,12 @@ int pm_clk_add(struct device *dev, const char *con_id)
72/** 90/**
73 * __pm_clk_remove - Destroy PM clock entry. 91 * __pm_clk_remove - Destroy PM clock entry.
74 * @ce: PM clock entry to destroy. 92 * @ce: PM clock entry to destroy.
75 *
76 * This routine must be called under the spinlock protecting the PM list of
77 * clocks corresponding the the @ce's device.
78 */ 93 */
79static void __pm_clk_remove(struct pm_clock_entry *ce) 94static void __pm_clk_remove(struct pm_clock_entry *ce)
80{ 95{
81 if (!ce) 96 if (!ce)
82 return; 97 return;
83 98
84 list_del(&ce->node);
85
86 if (ce->status < PCE_STATUS_ERROR) { 99 if (ce->status < PCE_STATUS_ERROR) {
87 if (ce->status == PCE_STATUS_ENABLED) 100 if (ce->status == PCE_STATUS_ENABLED)
88 clk_disable(ce->clk); 101 clk_disable(ce->clk);
@@ -116,18 +129,22 @@ void pm_clk_remove(struct device *dev, const char *con_id)
116 spin_lock_irq(&psd->lock); 129 spin_lock_irq(&psd->lock);
117 130
118 list_for_each_entry(ce, &psd->clock_list, node) { 131 list_for_each_entry(ce, &psd->clock_list, node) {
119 if (!con_id && !ce->con_id) { 132 if (!con_id && !ce->con_id)
120 __pm_clk_remove(ce); 133 goto remove;
121 break; 134 else if (!con_id || !ce->con_id)
122 } else if (!con_id || !ce->con_id) {
123 continue; 135 continue;
124 } else if (!strcmp(con_id, ce->con_id)) { 136 else if (!strcmp(con_id, ce->con_id))
125 __pm_clk_remove(ce); 137 goto remove;
126 break;
127 }
128 } 138 }
129 139
130 spin_unlock_irq(&psd->lock); 140 spin_unlock_irq(&psd->lock);
141 return;
142
143 remove:
144 list_del(&ce->node);
145 spin_unlock_irq(&psd->lock);
146
147 __pm_clk_remove(ce);
131} 148}
132 149
133/** 150/**
@@ -169,18 +186,26 @@ void pm_clk_destroy(struct device *dev)
169{ 186{
170 struct pm_subsys_data *psd = dev_to_psd(dev); 187 struct pm_subsys_data *psd = dev_to_psd(dev);
171 struct pm_clock_entry *ce, *c; 188 struct pm_clock_entry *ce, *c;
189 struct list_head list;
172 190
173 if (!psd) 191 if (!psd)
174 return; 192 return;
175 193
194 INIT_LIST_HEAD(&list);
195
176 spin_lock_irq(&psd->lock); 196 spin_lock_irq(&psd->lock);
177 197
178 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) 198 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
179 __pm_clk_remove(ce); 199 list_move(&ce->node, &list);
180 200
181 spin_unlock_irq(&psd->lock); 201 spin_unlock_irq(&psd->lock);
182 202
183 dev_pm_put_subsys_data(dev); 203 dev_pm_put_subsys_data(dev);
204
205 list_for_each_entry_safe_reverse(ce, c, &list, node) {
206 list_del(&ce->node);
207 __pm_clk_remove(ce);
208 }
184} 209}
185 210
186#endif /* CONFIG_PM */ 211#endif /* CONFIG_PM */
@@ -188,23 +213,6 @@ void pm_clk_destroy(struct device *dev)
188#ifdef CONFIG_PM_RUNTIME 213#ifdef CONFIG_PM_RUNTIME
189 214
190/** 215/**
191 * pm_clk_acquire - Acquire a device clock.
192 * @dev: Device whose clock is to be acquired.
193 * @con_id: Connection ID of the clock.
194 */
195static void pm_clk_acquire(struct device *dev,
196 struct pm_clock_entry *ce)
197{
198 ce->clk = clk_get(dev, ce->con_id);
199 if (IS_ERR(ce->clk)) {
200 ce->status = PCE_STATUS_ERROR;
201 } else {
202 ce->status = PCE_STATUS_ACQUIRED;
203 dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
204 }
205}
206
207/**
208 * pm_clk_suspend - Disable clocks in a device's PM clock list. 216 * pm_clk_suspend - Disable clocks in a device's PM clock list.
209 * @dev: Device to disable the clocks for. 217 * @dev: Device to disable the clocks for.
210 */ 218 */
@@ -222,9 +230,6 @@ int pm_clk_suspend(struct device *dev)
222 spin_lock_irqsave(&psd->lock, flags); 230 spin_lock_irqsave(&psd->lock, flags);
223 231
224 list_for_each_entry_reverse(ce, &psd->clock_list, node) { 232 list_for_each_entry_reverse(ce, &psd->clock_list, node) {
225 if (ce->status == PCE_STATUS_NONE)
226 pm_clk_acquire(dev, ce);
227
228 if (ce->status < PCE_STATUS_ERROR) { 233 if (ce->status < PCE_STATUS_ERROR) {
229 clk_disable(ce->clk); 234 clk_disable(ce->clk);
230 ce->status = PCE_STATUS_ACQUIRED; 235 ce->status = PCE_STATUS_ACQUIRED;
@@ -254,9 +259,6 @@ int pm_clk_resume(struct device *dev)
254 spin_lock_irqsave(&psd->lock, flags); 259 spin_lock_irqsave(&psd->lock, flags);
255 260
256 list_for_each_entry(ce, &psd->clock_list, node) { 261 list_for_each_entry(ce, &psd->clock_list, node) {
257 if (ce->status == PCE_STATUS_NONE)
258 pm_clk_acquire(dev, ce);
259
260 if (ce->status < PCE_STATUS_ERROR) { 262 if (ce->status < PCE_STATUS_ERROR) {
261 clk_enable(ce->clk); 263 clk_enable(ce->clk);
262 ce->status = PCE_STATUS_ENABLED; 264 ce->status = PCE_STATUS_ENABLED;
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 0eef4da1ac6..20663f8dae4 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -168,13 +168,11 @@ struct regmap *regmap_init(struct device *dev,
168 map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); 168 map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
169 if (map->work_buf == NULL) { 169 if (map->work_buf == NULL) {
170 ret = -ENOMEM; 170 ret = -ENOMEM;
171 goto err_bus; 171 goto err_map;
172 } 172 }
173 173
174 return map; 174 return map;
175 175
176err_bus:
177 module_put(map->bus->owner);
178err_map: 176err_map:
179 kfree(map); 177 kfree(map);
180err: 178err:
@@ -188,7 +186,6 @@ EXPORT_SYMBOL_GPL(regmap_init);
188void regmap_exit(struct regmap *map) 186void regmap_exit(struct regmap *map)
189{ 187{
190 kfree(map->work_buf); 188 kfree(map->work_buf);
191 module_put(map->bus->owner);
192 kfree(map); 189 kfree(map);
193} 190}
194EXPORT_SYMBOL_GPL(regmap_exit); 191EXPORT_SYMBOL_GPL(regmap_exit);