Merge tag 'pm-5.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2019 17:30:06 +0000 (10:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2019 17:30:06 +0000 (10:30 -0700)
Pull more power management updates from Rafael Wysocki:
 "These are mostly fixes and cleanups on top of the previously merged
  power management material for 5.1-rc1 with one cpupower utility update
  that wasn't pushed earlier due to unfortunate timing.

  Specifics:

   - Fix registration of new cpuidle governors partially broken during
     the 5.0 development cycle by mistake (Rafael Wysocki).

   - Avoid integer overflows in the menu cpuidle governor by making it
     discard the overflowing data points upfront (Rafael Wysocki).

   - Fix minor mistake in the recent update of the iowait boost
     computation in the intel_pstate driver (Rafael Wysocki).

   - Drop incorrect __init annotation from one function in the pxa2xx
     cpufreq driver (Arnd Bergmann).

   - Fix the operating performance points (OPP) framework initialization
     for devices in multiple power domains if only one of them is
     scalable (Rajendra Nayak).

   - Fix mistake in dev_pm_opp_set_rate() which causes it to skip
     updating the performance state if the new frequency is the same as
     the old one (Viresh Kumar).

   - Rework the cancellation of wakeup source timers to avoid potential
     issues with it and do some cleanups unlocked by that change (Viresh
     Kumar, Rafael Wysocki).

   - Clean up the code computing the active/suspended time of devices in
     the PM-runtime framework after recent changes (Ulf Hansson).

   - Make the power management infrastructure code use pr_fmt()
     consistently (Joe Perches).

   - Clean up the generic power domains (genpd) framework somewhat
     (Aisheng Dong).

   - Improve kerneldoc comments for two functions in the cpufreq core
     (Rafael Wysocki).

   - Fix typo in a PM QoS file description comment (Aisheng Dong).

   - Update the handling of CPU boost frequencies in the cpupower
     utility (Abhishek Goel)"

* tag 'pm-5.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: governor: Add new governors to cpuidle_governors again
  cpufreq: intel_pstate: Fix up iowait_boost computation
  PM / OPP: Update performance state when freq == old_freq
  PM / wakeup: Drop wakeup_source_drop()
  PM / wakeup: Rework wakeup source timer cancellation
  PM / domains: Remove one unnecessary blank line
  PM / Domains: Return early for all errors in _genpd_power_off()
  PM / Domains: Improve warn for multiple states but no governor
  OPP: Fix handling of multiple power domains
  PM / QoS: Fix typo in file description
  cpufreq: pxa2xx: remove incorrect __init annotation
  PM-runtime: Call pm_runtime_active|suspended_time() from sysfs
  PM-runtime: Consolidate code to get active/suspended time
  PM: Add and use pr_fmt()
  cpufreq: Improve kerneldoc comments for cpufreq_cpu_get/put()
  cpuidle: menu: Avoid overflows when computing variance
  tools/power/cpupower: Display boost frequency separately

1  2 
drivers/base/power/main.c
drivers/base/power/runtime.c

@@@ -17,6 -17,8 +17,8 @@@
   * subsystem list maintains.
   */
  
+ #define pr_fmt(fmt) "PM: " fmt
  #include <linux/device.h>
  #include <linux/export.h>
  #include <linux/mutex.h>
@@@ -128,7 -130,7 +130,7 @@@ void device_pm_add(struct device *dev
        if (device_pm_not_required(dev))
                return;
  
-       pr_debug("PM: Adding info for %s:%s\n",
+       pr_debug("Adding info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
        device_pm_check_callbacks(dev);
        mutex_lock(&dpm_list_mtx);
@@@ -149,7 -151,7 +151,7 @@@ void device_pm_remove(struct device *de
        if (device_pm_not_required(dev))
                return;
  
-       pr_debug("PM: Removing info for %s:%s\n",
+       pr_debug("Removing info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
        complete_all(&dev->power.completion);
        mutex_lock(&dpm_list_mtx);
   */
  void device_pm_move_before(struct device *deva, struct device *devb)
  {
-       pr_debug("PM: Moving %s:%s before %s:%s\n",
+       pr_debug("Moving %s:%s before %s:%s\n",
                 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
                 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
        /* Delete deva from dpm_list and reinsert before devb. */
   */
  void device_pm_move_after(struct device *deva, struct device *devb)
  {
-       pr_debug("PM: Moving %s:%s after %s:%s\n",
+       pr_debug("Moving %s:%s after %s:%s\n",
                 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
                 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
        /* Delete deva from dpm_list and reinsert after devb. */
   */
  void device_pm_move_last(struct device *dev)
  {
-       pr_debug("PM: Moving %s:%s to end of list\n",
+       pr_debug("Moving %s:%s to end of list\n",
                 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
        list_move_tail(&dev->power.entry, &dpm_list);
  }
@@@ -418,8 -420,8 +420,8 @@@ static void pm_dev_dbg(struct device *d
  static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
                        int error)
  {
-       printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
-               dev_name(dev), pm_verb(state.event), info, error);
+       pr_err("Device %s failed to %s%s: error %d\n",
+              dev_name(dev), pm_verb(state.event), info, error);
  }
  
  static void dpm_show_time(ktime_t starttime, pm_message_t state, int error,
@@@ -734,7 -736,7 +736,7 @@@ void dpm_noirq_resume_devices(pm_messag
                reinit_completion(&dev->power.completion);
                if (is_async(dev)) {
                        get_device(dev);
 -                      async_schedule(async_resume_noirq, dev);
 +                      async_schedule_dev(async_resume_noirq, dev);
                }
        }
  
@@@ -891,7 -893,7 +893,7 @@@ void dpm_resume_early(pm_message_t stat
                reinit_completion(&dev->power.completion);
                if (is_async(dev)) {
                        get_device(dev);
 -                      async_schedule(async_resume_early, dev);
 +                      async_schedule_dev(async_resume_early, dev);
                }
        }
  
@@@ -1055,7 -1057,7 +1057,7 @@@ void dpm_resume(pm_message_t state
                reinit_completion(&dev->power.completion);
                if (is_async(dev)) {
                        get_device(dev);
 -                      async_schedule(async_resume, dev);
 +                      async_schedule_dev(async_resume, dev);
                }
        }
  
@@@ -1375,7 -1377,7 +1377,7 @@@ static int device_suspend_noirq(struct 
  
        if (is_async(dev)) {
                get_device(dev);
 -              async_schedule(async_suspend_noirq, dev);
 +              async_schedule_dev(async_suspend_noirq, dev);
                return 0;
        }
        return __device_suspend_noirq(dev, pm_transition, false);
@@@ -1578,7 -1580,7 +1580,7 @@@ static int device_suspend_late(struct d
  
        if (is_async(dev)) {
                get_device(dev);
 -              async_schedule(async_suspend_late, dev);
 +              async_schedule_dev(async_suspend_late, dev);
                return 0;
        }
  
@@@ -1844,7 -1846,7 +1846,7 @@@ static int device_suspend(struct devic
  
        if (is_async(dev)) {
                get_device(dev);
 -              async_schedule(async_suspend, dev);
 +              async_schedule_dev(async_suspend, dev);
                return 0;
        }
  
@@@ -2022,8 -2024,7 +2024,7 @@@ int dpm_prepare(pm_message_t state
                                error = 0;
                                continue;
                        }
-                       printk(KERN_INFO "PM: Device %s not prepared "
-                               "for power transition: code %d\n",
+                       pr_info("Device %s not prepared for power transition: code %d\n",
                                dev_name(dev), error);
                        put_device(dev);
                        break;
@@@ -2062,7 -2063,7 +2063,7 @@@ EXPORT_SYMBOL_GPL(dpm_suspend_start)
  void __suspend_report_result(const char *function, void *fn, int ret)
  {
        if (ret)
-               printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
+               pr_err("%s(): %pF returns %d\n", function, fn, ret);
  }
  EXPORT_SYMBOL_GPL(__suspend_report_result);
  
@@@ -64,7 -64,7 +64,7 @@@ static int rpm_suspend(struct device *d
   * runtime_status field is updated, to account the time in the old state
   * correctly.
   */
- void update_pm_runtime_accounting(struct device *dev)
static void update_pm_runtime_accounting(struct device *dev)
  {
        u64 now, last, delta;
  
@@@ -98,7 -98,7 +98,7 @@@ static void __update_runtime_status(str
        dev->power.runtime_status = status;
  }
  
u64 pm_runtime_suspended_time(struct device *dev)
static u64 rpm_get_accounted_time(struct device *dev, bool suspended)
  {
        u64 time;
        unsigned long flags;
        spin_lock_irqsave(&dev->power.lock, flags);
  
        update_pm_runtime_accounting(dev);
-       time = dev->power.suspended_time;
+       time = suspended ? dev->power.suspended_time : dev->power.active_time;
  
        spin_unlock_irqrestore(&dev->power.lock, flags);
  
        return time;
  }
+ u64 pm_runtime_active_time(struct device *dev)
+ {
+       return rpm_get_accounted_time(dev, false);
+ }
+ u64 pm_runtime_suspended_time(struct device *dev)
+ {
+       return rpm_get_accounted_time(dev, true);
+ }
  EXPORT_SYMBOL_GPL(pm_runtime_suspended_time);
  
  /**
@@@ -282,8 -292,11 +292,8 @@@ static int rpm_get_suppliers(struct dev
        list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
                int retval;
  
 -              if (!(link->flags & DL_FLAG_PM_RUNTIME))
 -                      continue;
 -
 -              if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND ||
 -                  link->rpm_active)
 +              if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
 +                  READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
                        continue;
  
                retval = pm_runtime_get_sync(link->supplier);
                        pm_runtime_put_noidle(link->supplier);
                        return retval;
                }
 -              link->rpm_active = true;
 +              refcount_inc(&link->rpm_active);
        }
        return 0;
  }
@@@ -301,13 -314,12 +311,13 @@@ static void rpm_put_suppliers(struct de
  {
        struct device_link *link;
  
 -      list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
 -              if (link->rpm_active &&
 -                  READ_ONCE(link->status) != DL_STATE_SUPPLIER_UNBIND) {
 +      list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
 +              if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
 +                      continue;
 +
 +              while (refcount_dec_not_one(&link->rpm_active))
                        pm_runtime_put(link->supplier);
 -                      link->rpm_active = false;
 -              }
 +      }
  }
  
  /**
@@@ -1112,57 -1124,24 +1122,57 @@@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_
   * and the device parent's counter of unsuspended children is modified to
   * reflect the new status.  If the new status is RPM_SUSPENDED, an idle
   * notification request for the parent is submitted.
 + *
 + * If @dev has any suppliers (as reflected by device links to them), and @status
 + * is RPM_ACTIVE, they will be activated upfront and if the activation of one
 + * of them fails, the status of @dev will be changed to RPM_SUSPENDED (instead
 + * of the @status value) and the suppliers will be deacticated on exit.  The
 + * error returned by the failing supplier activation will be returned in that
 + * case.
   */
  int __pm_runtime_set_status(struct device *dev, unsigned int status)
  {
        struct device *parent = dev->parent;
 -      unsigned long flags;
        bool notify_parent = false;
        int error = 0;
  
        if (status != RPM_ACTIVE && status != RPM_SUSPENDED)
                return -EINVAL;
  
 -      spin_lock_irqsave(&dev->power.lock, flags);
 +      spin_lock_irq(&dev->power.lock);
  
 -      if (!dev->power.runtime_error && !dev->power.disable_depth) {
 +      /*
 +       * Prevent PM-runtime from being enabled for the device or return an
 +       * error if it is enabled already and working.
 +       */
 +      if (dev->power.runtime_error || dev->power.disable_depth)
 +              dev->power.disable_depth++;
 +      else
                error = -EAGAIN;
 -              goto out;
 +
 +      spin_unlock_irq(&dev->power.lock);
 +
 +      if (error)
 +              return error;
 +
 +      /*
 +       * If the new status is RPM_ACTIVE, the suppliers can be activated
 +       * upfront regardless of the current status, because next time
 +       * rpm_put_suppliers() runs, the rpm_active refcounts of the links
 +       * involved will be dropped down to one anyway.
 +       */
 +      if (status == RPM_ACTIVE) {
 +              int idx = device_links_read_lock();
 +
 +              error = rpm_get_suppliers(dev);
 +              if (error)
 +                      status = RPM_SUSPENDED;
 +
 +              device_links_read_unlock(idx);
        }
  
 +      spin_lock_irq(&dev->power.lock);
 +
        if (dev->power.runtime_status == status || !parent)
                goto out_set;
  
  
                spin_unlock(&parent->power.lock);
  
 -              if (error)
 +              if (error) {
 +                      status = RPM_SUSPENDED;
                        goto out;
 +              }
        }
  
   out_set:
        __update_runtime_status(dev, status);
 -      dev->power.runtime_error = 0;
 +      if (!error)
 +              dev->power.runtime_error = 0;
 +
   out:
 -      spin_unlock_irqrestore(&dev->power.lock, flags);
 +      spin_unlock_irq(&dev->power.lock);
  
        if (notify_parent)
                pm_request_idle(parent);
  
 +      if (status == RPM_SUSPENDED) {
 +              int idx = device_links_read_lock();
 +
 +              rpm_put_suppliers(dev);
 +
 +              device_links_read_unlock(idx);
 +      }
 +
 +      pm_runtime_enable(dev);
 +
        return error;
  }
  EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
@@@ -1614,7 -1579,7 +1624,7 @@@ void pm_runtime_remove(struct device *d
   *
   * Check links from this device to any consumers and if any of them have active
   * runtime PM references to the device, drop the usage counter of the device
 - * (once per link).
 + * (as many times as needed).
   *
   * Links with the DL_FLAG_STATELESS flag set are ignored.
   *
@@@ -1636,8 -1601,10 +1646,8 @@@ void pm_runtime_clean_up_links(struct d
                if (link->flags & DL_FLAG_STATELESS)
                        continue;
  
 -              if (link->rpm_active) {
 +              while (refcount_dec_not_one(&link->rpm_active))
                        pm_runtime_put_noidle(dev);
 -                      link->rpm_active = false;
 -              }
        }
  
        device_links_read_unlock(idx);
@@@ -1655,11 -1622,8 +1665,11 @@@ void pm_runtime_get_suppliers(struct de
        idx = device_links_read_lock();
  
        list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
 -              if (link->flags & DL_FLAG_PM_RUNTIME)
 +              if (link->flags & DL_FLAG_PM_RUNTIME) {
 +                      link->supplier_preactivated = true;
 +                      refcount_inc(&link->rpm_active);
                        pm_runtime_get_sync(link->supplier);
 +              }
  
        device_links_read_unlock(idx);
  }
@@@ -1676,11 -1640,8 +1686,11 @@@ void pm_runtime_put_suppliers(struct de
        idx = device_links_read_lock();
  
        list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
 -              if (link->flags & DL_FLAG_PM_RUNTIME)
 -                      pm_runtime_put(link->supplier);
 +              if (link->supplier_preactivated) {
 +                      link->supplier_preactivated = false;
 +                      if (refcount_dec_not_one(&link->rpm_active))
 +                              pm_runtime_put(link->supplier);
 +              }
  
        device_links_read_unlock(idx);
  }
@@@ -1694,6 -1655,8 +1704,6 @@@ void pm_runtime_new_link(struct device 
  
  void pm_runtime_drop_link(struct device *dev)
  {
 -      rpm_put_suppliers(dev);
 -
        spin_lock_irq(&dev->power.lock);
        WARN_ON(dev->power.links_count == 0);
        dev->power.links_count--;