diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-09-26 20:12:45 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-09-26 20:12:45 +0200 |
commit | 0d41da2e31e81f5c8aaabe17f769de4304b2d4c8 (patch) | |
tree | 540acefba9bf01d3880d7bacb767fbf9b1fe80b4 /drivers/base | |
parent | a0089bd617adea27ebc352e1e0871649ab1dbaa6 (diff) | |
parent | e8b364b88cc4001b21c28c1ecf1e1e3ffbe162e6 (diff) | |
download | linux-stable-0d41da2e31e81f5c8aaabe17f769de4304b2d4c8.tar.gz linux-stable-0d41da2e31e81f5c8aaabe17f769de4304b2d4c8.tar.bz2 linux-stable-0d41da2e31e81f5c8aaabe17f769de4304b2d4c8.zip |
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.c | 1 | ||||
-rw-r--r-- | drivers/base/devtmpfs.c | 2 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 11 | ||||
-rw-r--r-- | drivers/base/platform.c | 2 | ||||
-rw-r--r-- | drivers/base/power/clock_ops.c | 76 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 5 |
6 files changed, 49 insertions, 48 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index cf7a0c788052..65cd74832450 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -397,6 +397,7 @@ static int remove_nodes(struct device *dev, static int release_nodes(struct device *dev, struct list_head *first, struct list_head *end, unsigned long flags) + __releases(&dev->devres_lock) { LIST_HEAD(todo); int cnt; diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 33e1bed68fdd..a4760e095ff5 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -376,7 +376,7 @@ int devtmpfs_mount(const char *mntdir) return err; } -static __initdata DECLARE_COMPLETION(setup_done); +static DECLARE_COMPLETION(setup_done); static int handle(const char *name, mode_t mode, struct device *dev) { diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index bbb03e6f7255..06ed6b4e7df5 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, if (!firmware_p) return -EINVAL; - if (WARN_ON(usermodehelper_is_disabled())) { - dev_err(device, "firmware: %s will not be loaded\n", name); - return -EBUSY; - } - *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) { dev_err(device, "%s: kmalloc(struct firmware) failed\n", @@ -539,6 +534,12 @@ static int _request_firmware(const struct firmware **firmware_p, return 0; } + if (WARN_ON(usermodehelper_is_disabled())) { + dev_err(device, "firmware: %s will not be loaded\n", name); + retval = -EBUSY; + goto out; + } + if (uevent) dev_dbg(device, "firmware: requesting %s\n", name); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0cad9c7f6bb5..99a5272d7c2f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(platform_bus); /** * arch_setup_pdev_archdata - Allow manipulation of archdata before its used - * @dev: platform device + * @pdev: platform device * * This is called before platform_device_add() such that any pdev_archdata may * 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 cb44b58d6813..b876e60a53ef 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -32,6 +32,22 @@ struct pm_clock_entry { }; /** + * pm_clk_acquire - Acquire a device clock. + * @dev: Device whose clock is to be acquired. + * @ce: PM clock entry corresponding to the clock. + */ +static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) +{ + ce->clk = clk_get(dev, ce->con_id); + if (IS_ERR(ce->clk)) { + ce->status = PCE_STATUS_ERROR; + } else { + ce->status = PCE_STATUS_ACQUIRED; + dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); + } +} + +/** * pm_clk_add - Start using a device clock for power management. * @dev: Device whose clock is going to be used for power management. * @con_id: Connection ID of the clock. @@ -63,6 +79,8 @@ int pm_clk_add(struct device *dev, const char *con_id) } } + pm_clk_acquire(dev, ce); + spin_lock_irq(&psd->lock); list_add_tail(&ce->node, &psd->clock_list); spin_unlock_irq(&psd->lock); @@ -72,17 +90,12 @@ int pm_clk_add(struct device *dev, const char *con_id) /** * __pm_clk_remove - Destroy PM clock entry. * @ce: PM clock entry to destroy. - * - * This routine must be called under the spinlock protecting the PM list of - * clocks corresponding the the @ce's device. */ static void __pm_clk_remove(struct pm_clock_entry *ce) { if (!ce) return; - list_del(&ce->node); - if (ce->status < PCE_STATUS_ERROR) { if (ce->status == PCE_STATUS_ENABLED) clk_disable(ce->clk); @@ -116,18 +129,22 @@ void pm_clk_remove(struct device *dev, const char *con_id) spin_lock_irq(&psd->lock); list_for_each_entry(ce, &psd->clock_list, node) { - if (!con_id && !ce->con_id) { - __pm_clk_remove(ce); - break; - } else if (!con_id || !ce->con_id) { + if (!con_id && !ce->con_id) + goto remove; + else if (!con_id || !ce->con_id) continue; - } else if (!strcmp(con_id, ce->con_id)) { - __pm_clk_remove(ce); - break; - } + else if (!strcmp(con_id, ce->con_id)) + goto remove; } spin_unlock_irq(&psd->lock); + return; + + remove: + list_del(&ce->node); + spin_unlock_irq(&psd->lock); + + __pm_clk_remove(ce); } /** @@ -169,18 +186,26 @@ void pm_clk_destroy(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce, *c; + struct list_head list; if (!psd) return; + INIT_LIST_HEAD(&list); + spin_lock_irq(&psd->lock); list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) - __pm_clk_remove(ce); + list_move(&ce->node, &list); spin_unlock_irq(&psd->lock); dev_pm_put_subsys_data(dev); + + list_for_each_entry_safe_reverse(ce, c, &list, node) { + list_del(&ce->node); + __pm_clk_remove(ce); + } } #endif /* CONFIG_PM */ @@ -188,23 +213,6 @@ void pm_clk_destroy(struct device *dev) #ifdef CONFIG_PM_RUNTIME /** - * pm_clk_acquire - Acquire a device clock. - * @dev: Device whose clock is to be acquired. - * @con_id: Connection ID of the clock. - */ -static void pm_clk_acquire(struct device *dev, - struct pm_clock_entry *ce) -{ - ce->clk = clk_get(dev, ce->con_id); - if (IS_ERR(ce->clk)) { - ce->status = PCE_STATUS_ERROR; - } else { - ce->status = PCE_STATUS_ACQUIRED; - dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); - } -} - -/** * pm_clk_suspend - Disable clocks in a device's PM clock list. * @dev: Device to disable the clocks for. */ @@ -222,9 +230,6 @@ int pm_clk_suspend(struct device *dev) spin_lock_irqsave(&psd->lock, flags); list_for_each_entry_reverse(ce, &psd->clock_list, node) { - if (ce->status == PCE_STATUS_NONE) - pm_clk_acquire(dev, ce); - if (ce->status < PCE_STATUS_ERROR) { clk_disable(ce->clk); ce->status = PCE_STATUS_ACQUIRED; @@ -254,9 +259,6 @@ int pm_clk_resume(struct device *dev) spin_lock_irqsave(&psd->lock, flags); list_for_each_entry(ce, &psd->clock_list, node) { - if (ce->status == PCE_STATUS_NONE) - pm_clk_acquire(dev, ce); - if (ce->status < PCE_STATUS_ERROR) { clk_enable(ce->clk); ce->status = PCE_STATUS_ENABLED; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0eef4da1ac61..20663f8dae45 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -168,13 +168,11 @@ struct regmap *regmap_init(struct device *dev, map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); if (map->work_buf == NULL) { ret = -ENOMEM; - goto err_bus; + goto err_map; } return map; -err_bus: - module_put(map->bus->owner); err_map: kfree(map); err: @@ -188,7 +186,6 @@ EXPORT_SYMBOL_GPL(regmap_init); void regmap_exit(struct regmap *map) { kfree(map->work_buf); - module_put(map->bus->owner); kfree(map); } EXPORT_SYMBOL_GPL(regmap_exit); |