From: Rafael J. Wysocki Date: Mon, 26 Sep 2011 18:12:45 +0000 (+0200) Subject: Merge branch 'pm-fixes' into pm-domains X-Git-Tag: upstream/snapshot3+hdmi~8938^2~3^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0d41da2e31e81f5c8aaabe17f769de4304b2d4c8;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git 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 --- 0d41da2e31e81f5c8aaabe17f769de4304b2d4c8 diff --cc drivers/base/power/clock_ops.c index cb44b58,b97294e..b876e60 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@@ -31,7 -36,28 +31,23 @@@ struct pm_clock_entry enum pce_status status; }; -static struct pm_clk_data *__to_pcd(struct device *dev) -{ - return dev ? dev->power.subsys_data : NULL; -} - /** + * 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,9 -89,11 +79,11 @@@ int pm_clk_add(struct device *dev, cons } } + pm_clk_acquire(dev, ce); + - spin_lock_irq(&pcd->lock); - list_add_tail(&ce->node, &pcd->clock_list); - spin_unlock_irq(&pcd->lock); + spin_lock_irq(&psd->lock); + list_add_tail(&ce->node, &psd->clock_list); + spin_unlock_irq(&psd->lock); return 0; } @@@ -107,27 -130,31 +120,31 @@@ static void __pm_clk_remove(struct pm_c */ void pm_clk_remove(struct device *dev, const char *con_id) { - struct pm_clk_data *pcd = __to_pcd(dev); + struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; - if (!pcd) + if (!psd) return; - spin_lock_irq(&pcd->lock); + spin_lock_irq(&psd->lock); - list_for_each_entry(ce, &pcd->clock_list, node) { + 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(&pcd->lock); + spin_unlock_irq(&psd->lock); + return; + + remove: + list_del(&ce->node); - spin_unlock_irq(&pcd->lock); ++ spin_unlock_irq(&psd->lock); + + __pm_clk_remove(ce); } /** @@@ -167,20 -190,29 +184,28 @@@ int pm_clk_create(struct device *dev */ void pm_clk_destroy(struct device *dev) { - struct pm_clk_data *pcd = __to_pcd(dev); + struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce, *c; + struct list_head list; - if (!pcd) + if (!psd) return; - dev->power.subsys_data = NULL; + INIT_LIST_HEAD(&list); + - spin_lock_irq(&pcd->lock); + spin_lock_irq(&psd->lock); - list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node) + list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) - __pm_clk_remove(ce); + list_move(&ce->node, &list); - spin_unlock_irq(&pcd->lock); + spin_unlock_irq(&psd->lock); - kfree(pcd); + 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 */ @@@ -216,15 -231,12 +224,12 @@@ int pm_clk_suspend(struct device *dev dev_dbg(dev, "%s()\n", __func__); - if (!pcd) + if (!psd) return 0; - spin_lock_irqsave(&pcd->lock, flags); + spin_lock_irqsave(&psd->lock, flags); - list_for_each_entry_reverse(ce, &pcd->clock_list, node) { + 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; @@@ -248,15 -260,12 +253,12 @@@ int pm_clk_resume(struct device *dev dev_dbg(dev, "%s()\n", __func__); - if (!pcd) + if (!psd) return 0; - spin_lock_irqsave(&pcd->lock, flags); + spin_lock_irqsave(&psd->lock, flags); - list_for_each_entry(ce, &pcd->clock_list, node) { + 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;