Commit 6bd2c87a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These add PM QoS support to devfreq and fix a few issues in that
  subsystem, fix two cpuidle issues and do one minor cleanup in there,
  and address an ACPI power management problem related to devices with
  special power management requirements, like fans.

  Specifics:

   - Add PM QoS support, based on the frequency QoS introduced during
     the 5.4 cycle, to devfreq (Leonard Crestez).

   - Fix some assorted devfreq issues (Leonard Crestez).

   - Fix an unintentional cpuidle behavior change (introduced during the
     5.4 cycle) related to the active polling time limit (Marcelo
     Tosatti).

   - Fix a recently introduced cpuidle helper function and do a minor
     cleanup in the cpuidle core (Rafael Wysocki).

   - Avoid adding devices with special power management requirements,
     like fans, to the generic ACPI PM domain (Rafael Wysocki)"

* tag 'pm-5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: Drop unnecessary type cast in cpuidle_poll_time()
  cpuidle: Fix cpuidle_driver_state_disabled()
  ACPI: PM: Avoid attaching ACPI PM domain to certain devices
  cpuidle: use first valid target residency as poll time
  PM / devfreq: Use PM QoS for sysfs min/max_freq
  PM / devfreq: Add PM QoS support
  PM / devfreq: Don't fail devfreq_dev_release if not in list
  PM / devfreq: Introduce get_freq_range helper
  PM / devfreq: Set scaling_max_freq to max on OPP notifier error
  PM / devfreq: Fix devfreq_notifier_call returning errno
parents b61c5622 4c84515d
...@@ -1314,9 +1314,19 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) ...@@ -1314,9 +1314,19 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
*/ */
int acpi_dev_pm_attach(struct device *dev, bool power_on) int acpi_dev_pm_attach(struct device *dev, bool power_on)
{ {
/*
* Skip devices whose ACPI companions match the device IDs below,
* because they require special power management handling incompatible
* with the generic ACPI PM domain.
*/
static const struct acpi_device_id special_pm_ids[] = {
{"PNP0C0B", }, /* Generic ACPI fan */
{"INT3404", }, /* Fan */
{}
};
struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_device *adev = ACPI_COMPANION(dev);
if (!adev) if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
return 0; return 0;
/* /*
......
...@@ -381,7 +381,8 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv, ...@@ -381,7 +381,8 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv,
if (dev->states_usage[i].disable) if (dev->states_usage[i].disable)
continue; continue;
limit_ns = (u64)drv->states[i].target_residency_ns; limit_ns = drv->states[i].target_residency_ns;
break;
} }
dev->poll_limit_ns = limit_ns; dev->poll_limit_ns = limit_ns;
......
...@@ -403,6 +403,13 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx, ...@@ -403,6 +403,13 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
mutex_lock(&cpuidle_lock); mutex_lock(&cpuidle_lock);
spin_lock(&cpuidle_driver_lock);
if (!drv->cpumask) {
drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;
goto unlock;
}
for_each_cpu(cpu, drv->cpumask) { for_each_cpu(cpu, drv->cpumask) {
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu); struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
...@@ -415,5 +422,8 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx, ...@@ -415,5 +422,8 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER; dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;
} }
unlock:
spin_unlock(&cpuidle_driver_lock);
mutex_unlock(&cpuidle_lock); mutex_unlock(&cpuidle_lock);
} }
This diff is collapsed.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/pm_opp.h> #include <linux/pm_opp.h>
#include <linux/pm_qos.h>
#define DEVFREQ_NAME_LEN 16 #define DEVFREQ_NAME_LEN 16
...@@ -123,8 +124,8 @@ struct devfreq_dev_profile { ...@@ -123,8 +124,8 @@ struct devfreq_dev_profile {
* @previous_freq: previously configured frequency value. * @previous_freq: previously configured frequency value.
* @data: Private data of the governor. The devfreq framework does not * @data: Private data of the governor. The devfreq framework does not
* touch this. * touch this.
* @min_freq: Limit minimum frequency requested by user (0: none) * @user_min_freq_req: PM QoS minimum frequency request from user (via sysfs)
* @max_freq: Limit maximum frequency requested by user (0: none) * @user_max_freq_req: PM QoS maximum frequency request from user (via sysfs)
* @scaling_min_freq: Limit minimum frequency requested by OPP interface * @scaling_min_freq: Limit minimum frequency requested by OPP interface
* @scaling_max_freq: Limit maximum frequency requested by OPP interface * @scaling_max_freq: Limit maximum frequency requested by OPP interface
* @stop_polling: devfreq polling status of a device. * @stop_polling: devfreq polling status of a device.
...@@ -136,6 +137,8 @@ struct devfreq_dev_profile { ...@@ -136,6 +137,8 @@ struct devfreq_dev_profile {
* @time_in_state: Statistics of devfreq states * @time_in_state: Statistics of devfreq states
* @last_stat_updated: The last time stat updated * @last_stat_updated: The last time stat updated
* @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
* @nb_min: Notifier block for DEV_PM_QOS_MIN_FREQUENCY
* @nb_max: Notifier block for DEV_PM_QOS_MAX_FREQUENCY
* *
* This structure stores the devfreq information for a give device. * This structure stores the devfreq information for a give device.
* *
...@@ -161,8 +164,8 @@ struct devfreq { ...@@ -161,8 +164,8 @@ struct devfreq {
void *data; /* private data for governors */ void *data; /* private data for governors */
unsigned long min_freq; struct dev_pm_qos_request user_min_freq_req;
unsigned long max_freq; struct dev_pm_qos_request user_max_freq_req;
unsigned long scaling_min_freq; unsigned long scaling_min_freq;
unsigned long scaling_max_freq; unsigned long scaling_max_freq;
bool stop_polling; bool stop_polling;
...@@ -178,6 +181,9 @@ struct devfreq { ...@@ -178,6 +181,9 @@ struct devfreq {
unsigned long last_stat_updated; unsigned long last_stat_updated;
struct srcu_notifier_head transition_notifier_list; struct srcu_notifier_head transition_notifier_list;
struct notifier_block nb_min;
struct notifier_block nb_max;
}; };
struct devfreq_freqs { struct devfreq_freqs {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment