From: Rafael J. Wysocki <rjw@xxxxxxx> The lock member of struct pm_subsys_data is of type struct mutex, which is a problem, because the suspend and resume routines defined in drivers/base/power/clock_ops.c cannot be executed with interrupts disabled for this reason. Modify struct pm_subsys_data so that its lock member is a spinlock. Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx> --- drivers/base/power/clock_ops.c | 35 +++++++++++++++++++++-------------- drivers/base/power/common.c | 2 +- include/linux/pm.h | 2 +- 3 files changed, 23 insertions(+), 16 deletions(-) Index: linux/include/linux/pm.h =================================================================== --- linux.orig/include/linux/pm.h +++ linux/include/linux/pm.h @@ -438,7 +438,7 @@ struct pm_domain_data { }; struct pm_subsys_data { - struct mutex lock; + spinlock_t lock; unsigned int refcount; #ifdef CONFIG_PM_CLK struct list_head clock_list; Index: linux/drivers/base/power/clock_ops.c =================================================================== --- linux.orig/drivers/base/power/clock_ops.c +++ linux/drivers/base/power/clock_ops.c @@ -43,6 +43,7 @@ int pm_clk_add(struct device *dev, const { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; if (!psd) return -EINVAL; @@ -63,9 +64,9 @@ int pm_clk_add(struct device *dev, const } } - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_add_tail(&ce->node, &psd->clock_list); - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); return 0; } @@ -109,11 +110,12 @@ void pm_clk_remove(struct device *dev, c { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; if (!psd) return; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry(ce, &psd->clock_list, node) { if (!con_id && !ce->con_id) { @@ -127,7 +129,7 @@ void pm_clk_remove(struct device *dev, c } } - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); } /** @@ -169,16 +171,17 @@ void pm_clk_destroy(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce, *c; + unsigned long flags; if (!psd) return; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) __pm_clk_remove(ce); - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); dev_pm_put_subsys_data(dev); } @@ -212,13 +215,14 @@ int pm_clk_suspend(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; dev_dbg(dev, "%s()\n", __func__); if (!psd) return 0; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry_reverse(ce, &psd->clock_list, node) { if (ce->status == PCE_STATUS_NONE) @@ -230,7 +234,7 @@ int pm_clk_suspend(struct device *dev) } } - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); return 0; } @@ -243,13 +247,14 @@ int pm_clk_resume(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; dev_dbg(dev, "%s()\n", __func__); if (!psd) return 0; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry(ce, &psd->clock_list, node) { if (ce->status == PCE_STATUS_NONE) @@ -261,7 +266,7 @@ int pm_clk_resume(struct device *dev) } } - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); return 0; } @@ -336,6 +341,7 @@ int pm_clk_suspend(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; dev_dbg(dev, "%s()\n", __func__); @@ -343,12 +349,12 @@ int pm_clk_suspend(struct device *dev) if (!psd || !dev->driver) return 0; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry_reverse(ce, &psd->clock_list, node) clk_disable(ce->clk); - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); return 0; } @@ -361,6 +367,7 @@ int pm_clk_resume(struct device *dev) { struct pm_subsys_data *psd = dev_to_psd(dev); struct pm_clock_entry *ce; + unsigned long flags; dev_dbg(dev, "%s()\n", __func__); @@ -368,12 +375,12 @@ int pm_clk_resume(struct device *dev) if (!psd || !dev->driver) return 0; - mutex_lock(&psd->lock); + spin_lock_irqsave(&psd->lock, flags); list_for_each_entry(ce, &psd->clock_list, node) clk_enable(ce->clk); - mutex_unlock(&psd->lock); + spin_unlock_irqrestore(&psd->lock, flags); return 0; } Index: linux/drivers/base/power/common.c =================================================================== --- linux.orig/drivers/base/power/common.c +++ linux/drivers/base/power/common.c @@ -34,7 +34,7 @@ int dev_pm_get_subsys_data(struct device if (dev->power.subsys_data) { dev->power.subsys_data->refcount++; } else { - mutex_init(&psd->lock); + spin_lock_init(&psd->lock); psd->refcount = 1; dev->power.subsys_data = psd; pm_clk_init(dev); _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm