]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'pm-core'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 20 Jan 2016 23:42:59 +0000 (00:42 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 20 Jan 2016 23:42:59 +0000 (00:42 +0100)
* pm-core:
  driver core: Avoid NULL pointer dereferences in device_is_bound()
  platform: Do not detach from PM domains on shutdown
  USB / PM: Allow USB devices to remain runtime-suspended when sleeping
  PM / sleep: Go direct_complete if driver has no callbacks
  PM / Domains: add setter for dev.pm_domain
  device core: add device_is_bound()

1  2 
drivers/base/platform.c
drivers/base/power/domain.c
drivers/usb/core/port.c

diff --combined drivers/base/platform.c
index 8dcbb266643b8773e212bc29f3b2137c3060e059,484255c7bc476aee44232a9b2e0bf0db2b1aaa64..73d6e5d39e33e1edef9033d5e97b99ecc50a80cf
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/acpi.h>
  #include <linux/clk/clk-conf.h>
  #include <linux/limits.h>
 +#include <linux/property.h>
  
  #include "base.h"
  #include "power/power.h"
@@@ -117,26 -116,6 +117,26 @@@ int platform_get_irq(struct platform_de
  }
  EXPORT_SYMBOL_GPL(platform_get_irq);
  
 +/**
 + * platform_irq_count - Count the number of IRQs a platform device uses
 + * @dev: platform device
 + *
 + * Return: Number of IRQs a platform device uses or EPROBE_DEFER
 + */
 +int platform_irq_count(struct platform_device *dev)
 +{
 +      int ret, nr = 0;
 +
 +      while ((ret = platform_get_irq(dev, nr)) >= 0)
 +              nr++;
 +
 +      if (ret == -EPROBE_DEFER)
 +              return ret;
 +
 +      return nr;
 +}
 +EXPORT_SYMBOL_GPL(platform_irq_count);
 +
  /**
   * platform_get_resource_byname - get a resource for a device by name
   * @dev: platform device
@@@ -319,22 -298,6 +319,22 @@@ int platform_device_add_data(struct pla
  }
  EXPORT_SYMBOL_GPL(platform_device_add_data);
  
 +/**
 + * platform_device_add_properties - add built-in properties to a platform device
 + * @pdev: platform device to add properties to
 + * @pset: properties to add
 + *
 + * The function will take deep copy of the properties in @pset and attach
 + * the copy to the platform device. The memory associated with properties
 + * will be freed when the platform device is released.
 + */
 +int platform_device_add_properties(struct platform_device *pdev,
 +                                 const struct property_set *pset)
 +{
 +      return device_add_property_set(&pdev->dev, pset);
 +}
 +EXPORT_SYMBOL_GPL(platform_device_add_properties);
 +
  /**
   * platform_device_add - add a platform device to device hierarchy
   * @pdev: platform device we're adding
@@@ -446,8 -409,6 +446,8 @@@ void platform_device_del(struct platfor
                        if (r->parent)
                                release_resource(r);
                }
 +
 +              device_remove_property_set(&pdev->dev);
        }
  }
  EXPORT_SYMBOL_GPL(platform_device_del);
@@@ -526,12 -487,6 +526,12 @@@ struct platform_device *platform_device
        if (ret)
                goto err;
  
 +      if (pdevinfo->pset) {
 +              ret = platform_device_add_properties(pdev, pdevinfo->pset);
 +              if (ret)
 +                      goto err;
 +      }
 +
        ret = platform_device_add(pdev);
        if (ret) {
  err:
@@@ -597,7 -552,6 +597,6 @@@ static void platform_drv_shutdown(struc
  
        if (drv->shutdown)
                drv->shutdown(dev);
-       dev_pm_domain_detach(_dev, true);
  }
  
  /**
index b8037901284042790a80b12a0ef507f149019240,33a5f4b752ed7f69344f55060b69f9a507e7d41b..6ac9a7f33b640ae1105a72f76974e8939a30ae45
@@@ -20,6 -20,8 +20,8 @@@
  #include <linux/suspend.h>
  #include <linux/export.h>
  
+ #include "power.h"
  #define GENPD_RETRY_MAX_MS    250             /* Approximate */
  
  #define GENPD_DEV_CALLBACK(genpd, type, callback, dev)                \
@@@ -390,7 -392,6 +392,7 @@@ static int pm_genpd_runtime_suspend(str
        struct generic_pm_domain *genpd;
        bool (*stop_ok)(struct device *__dev);
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 +      bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
        if (IS_ERR(genpd))
                return -EINVAL;
  
 +      /*
 +       * A runtime PM centric subsystem/driver may re-use the runtime PM
 +       * callbacks for other purposes than runtime PM. In those scenarios
 +       * runtime PM is disabled. Under these circumstances, we shall skip
 +       * validating/measuring the PM QoS latency.
 +       */
        stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
 -      if (stop_ok && !stop_ok(dev))
 +      if (runtime_pm && stop_ok && !stop_ok(dev))
                return -EBUSY;
  
        /* Measure suspend latency. */
 -      time_start = ktime_get();
 +      if (runtime_pm)
 +              time_start = ktime_get();
  
        ret = genpd_save_dev(genpd, dev);
        if (ret)
        }
  
        /* Update suspend latency value if the measured time exceeds it. */
 -      elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 -      if (elapsed_ns > td->suspend_latency_ns) {
 -              td->suspend_latency_ns = elapsed_ns;
 -              dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
 -                      elapsed_ns);
 -              genpd->max_off_time_changed = true;
 -              td->constraint_changed = true;
 +      if (runtime_pm) {
 +              elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 +              if (elapsed_ns > td->suspend_latency_ns) {
 +                      td->suspend_latency_ns = elapsed_ns;
 +                      dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
 +                              elapsed_ns);
 +                      genpd->max_off_time_changed = true;
 +                      td->constraint_changed = true;
 +              }
        }
  
        /*
@@@ -463,7 -455,6 +465,7 @@@ static int pm_genpd_runtime_resume(stru
  {
        struct generic_pm_domain *genpd;
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 +      bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
  
   out:
        /* Measure resume latency. */
 -      if (timed)
 +      if (timed && runtime_pm)
                time_start = ktime_get();
  
        genpd_start_dev(genpd, dev);
        genpd_restore_dev(genpd, dev);
  
        /* Update resume latency value if the measured time exceeds it. */
 -      if (timed) {
 +      if (timed && runtime_pm) {
                elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
                if (elapsed_ns > td->resume_latency_ns) {
                        td->resume_latency_ns = elapsed_ns;
@@@ -1188,10 -1179,11 +1190,11 @@@ static struct generic_pm_domain_data *g
        }
  
        dev->power.subsys_data->domain_data = &gpd_data->base;
-       dev->pm_domain = &genpd->domain;
  
        spin_unlock_irq(&dev->power.lock);
  
+       dev_pm_domain_set(dev, &genpd->domain);
        return gpd_data;
  
   err_free:
  static void genpd_free_dev_data(struct device *dev,
                                struct generic_pm_domain_data *gpd_data)
  {
+       dev_pm_domain_set(dev, NULL);
        spin_lock_irq(&dev->power.lock);
  
-       dev->pm_domain = NULL;
        dev->power.subsys_data->domain_data = NULL;
  
        spin_unlock_irq(&dev->power.lock);
@@@ -1263,7 -1256,6 +1267,7 @@@ int __pm_genpd_add_device(struct generi
  
        return ret;
  }
 +EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
  
  /**
   * pm_genpd_remove_device - Remove a device from an I/O PM domain.
@@@ -1314,7 -1306,6 +1318,7 @@@ int pm_genpd_remove_device(struct gener
  
        return ret;
  }
 +EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
  
  /**
   * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
diff --combined drivers/usb/core/port.c
index 5487fe308f01b7be30bcecebc12726a295f9daa9,f49707d73b5acd11f95e5cc5182f025b5e003566..514b563e3e5fbc964107a31bbd18a7735d96e565
@@@ -168,12 -168,18 +168,18 @@@ static int usb_port_runtime_suspend(str
  
        return retval;
  }
+ static int usb_port_prepare(struct device *dev)
+ {
+       return 1;
+ }
  #endif
  
  static const struct dev_pm_ops usb_port_pm_ops = {
  #ifdef CONFIG_PM
        .runtime_suspend =      usb_port_runtime_suspend,
        .runtime_resume =       usb_port_runtime_resume,
+       .prepare =              usb_port_prepare,
  #endif
  };
  
@@@ -206,7 -212,7 +212,7 @@@ static int link_peers(struct usb_port *
                else
                        method = "default";
  
 -              pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
 +              pr_debug("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
                        dev_name(&left->dev), dev_name(&right->dev), method,
                        dev_name(&left->dev),
                        lpeer ? dev_name(&lpeer->dev) : "none",
@@@ -265,7 -271,7 +271,7 @@@ static void link_peers_report(struct us
        if (rc == 0) {
                dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev));
        } else {
 -              dev_warn(&left->dev, "failed to peer to %s (%d)\n",
 +              dev_dbg(&left->dev, "failed to peer to %s (%d)\n",
                                dev_name(&right->dev), rc);
                pr_warn_once("usb: port power management may be unreliable\n");
                usb_port_block_power_off = 1;