Merge branch 'pm-fixes' into pm-domains
authorRafael J. Wysocki <rjw@sisk.pl>
Mon, 26 Sep 2011 18:12:45 +0000 (20:12 +0200)
committerRafael J. Wysocki <rjw@sisk.pl>
Mon, 26 Sep 2011 18:12:45 +0000 (20:12 +0200)
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

1  2 
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/include/mach/sh7372.h
arch/arm/mach-shmobile/setup-sh7372.c
drivers/base/power/clock_ops.c

Simple merge
Simple merge
@@@ -31,6 -36,27 +31,22 @@@ 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.
@@@ -63,9 -89,11 +79,11 @@@ int pm_clk_add(struct device *dev, cons
                }
        }
  
 -      spin_lock_irq(&pcd->lock);
 -      list_add_tail(&ce->node, &pcd->clock_list);
 -      spin_unlock_irq(&pcd->lock);
+       pm_clk_acquire(dev, ce);
 +      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;