History

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

Pull power management fixes from Rafael Wysocki: "These add a check to avoid recent suspend-to-idle power regression on systems with NVMe drives where the PCIe ASPM policy is "performance" (or when the kernel is built without ASPM support), fix an issue related to frequency limits in the schedutil cpufreq governor and fix a mistake related to the PM QoS usage in the cpufreq core introduced recently. Specifics: - Disable NVMe power optimization related to suspend-to-idle added recently on systems where PCIe ASPM is not able to put PCIe links into low-power states to prevent excess power from being drawn by the system while suspended (Rafael Wysocki). - Make the schedutil governor handle frequency limits changes properly in all cases (Viresh Kumar). - Prevent the cpufreq core from treating positive values returned by dev_pm_qos_update_request() as errors (Viresh Kumar)" * tag 'pm-5.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: nvme-pci: Allow PCI bus-level PM to be used if ASPM is disabled PCI/ASPM: Add pcie_aspm_enabled() cpufreq: schedutil: Don't skip freq update when limits change cpufreq: dev_pm_qos_update_request() can return 1 on success

Linus Torvalds committed 7 years ago

Commit 2d63ba32 parents 9da5bb2 a3ee2475 files · +43 −8Browse files

Unified · Split

5 files
  1. drivers/cpufreq/cpufreq.c +1 −1
  2. drivers/nvme/host/pci.c +10 −3
  3. drivers/pci/pcie/aspm.c +20 −0
  4. include/linux/pci.h +2 −0
  5. kernel/sched/cpufreq_schedutil.c +10 −4
drivers/cpufreq/cpufreq.c+1−1
@@ -2528,7 +2528,7 @@ static int cpufreq_boost_set_sw(int state) · 2527 unmodified lines
2528 }2528 }
2529 2529
2530 ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);2530 ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
2531 if (ret)2531 if (ret < 0)
2532 break;2532 break;
2533 }2533 }
2534 2534
drivers/nvme/host/pci.c+10−3
@@ -2846,7 +2846,7 @@ static int nvme_resume(struct device *dev) · 2845 unmodified lines
2846 struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));2846 struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
2847 struct nvme_ctrl *ctrl = &ndev->ctrl;2847 struct nvme_ctrl *ctrl = &ndev->ctrl;
2848 2848
2849 if (pm_resume_via_firmware() || !ctrl->npss ||2849 if (ndev->last_ps == U32_MAX ||
2850 nvme_set_power_state(ctrl, ndev->last_ps) != 0)2850 nvme_set_power_state(ctrl, ndev->last_ps) != 0)
2851 nvme_reset_ctrl(ctrl);2851 nvme_reset_ctrl(ctrl);
2852 return 0;2852 return 0;
@@ -2859,6 +2859,8 @@ static int nvme_suspend(struct device *dev) · 6 unmodified lines
2859 struct nvme_ctrl *ctrl = &ndev->ctrl;2859 struct nvme_ctrl *ctrl = &ndev->ctrl;
2860 int ret = -EBUSY;2860 int ret = -EBUSY;
2861 2861
2862 ndev->last_ps = U32_MAX;
2863
2862 /*2864 /*
2863 * The platform does not remove power for a kernel managed suspend so2865 * The platform does not remove power for a kernel managed suspend so
2864 * use host managed nvme power settings for lowest idle power if2866 * use host managed nvme power settings for lowest idle power if
@@ -2866,8 +2868,14 @@ static int nvme_suspend(struct device *dev) · 1 unmodified line
2866 * shutdown. But if the firmware is involved after the suspend or the2868 * shutdown. But if the firmware is involved after the suspend or the
2867 * device does not support any non-default power states, shut down the2869 * device does not support any non-default power states, shut down the
2868 * device fully.2870 * device fully.
2871 *
2872 * If ASPM is not enabled for the device, shut down the device and allow
2873 * the PCI bus layer to put it into D3 in order to take the PCIe link
2874 * down, so as to allow the platform to achieve its minimum low-power
2875 * state (which may not be possible if the link is up).
2869 */2876 */
2870 if (pm_suspend_via_firmware() || !ctrl->npss) {2877 if (pm_suspend_via_firmware() || !ctrl->npss ||
2878 !pcie_aspm_enabled(pdev)) {
2871 nvme_dev_disable(ndev, true);2879 nvme_dev_disable(ndev, true);
2872 return 0;2880 return 0;
2873 }2881 }
@@ -2880,7 +2888,6 @@ static int nvme_suspend(struct device *dev) · 6 unmodified lines
2880 ctrl->state != NVME_CTRL_ADMIN_ONLY)2888 ctrl->state != NVME_CTRL_ADMIN_ONLY)
2881 goto unfreeze;2889 goto unfreeze;
2882 2890
2883 ndev->last_ps = 0;
2884 ret = nvme_get_power_state(ctrl, &ndev->last_ps);2891 ret = nvme_get_power_state(ctrl, &ndev->last_ps);
2885 if (ret < 0)2892 if (ret < 0)
2886 goto unfreeze;2893 goto unfreeze;
drivers/pci/pcie/aspm.c+20−0
@@ -1170,6 +1170,26 @@ static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp) · 1169 unmodified lines
1170module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,1170module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
1171 NULL, 0644);1171 NULL, 0644);
1172 1172
1173/**
1174 * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
1175 * @pdev: Target device.
1176 */
1177bool pcie_aspm_enabled(struct pci_dev *pdev)
1178{
1179 struct pci_dev *bridge = pci_upstream_bridge(pdev);
1180 bool ret;
1181
1182 if (!bridge)
1183 return false;
1184
1185 mutex_lock(&aspm_lock);
1186 ret = bridge->link_state ? !!bridge->link_state->aspm_enabled : false;
1187 mutex_unlock(&aspm_lock);
1188
1189 return ret;
1190}
1191EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
1192
1173#ifdef CONFIG_PCIEASPM_DEBUG1193#ifdef CONFIG_PCIEASPM_DEBUG
1174static ssize_t link_state_show(struct device *dev,1194static ssize_t link_state_show(struct device *dev,
1175 struct device_attribute *attr,1195 struct device_attribute *attr,
include/linux/pci.h+2−0
@@ -1567,8 +1567,10 @@ extern bool pcie_ports_native; · 1566 unmodified lines
1567 1567
1568#ifdef CONFIG_PCIEASPM1568#ifdef CONFIG_PCIEASPM
1569bool pcie_aspm_support_enabled(void);1569bool pcie_aspm_support_enabled(void);
1570bool pcie_aspm_enabled(struct pci_dev *pdev);
1570#else1571#else
1571static inline bool pcie_aspm_support_enabled(void) { return false; }1572static inline bool pcie_aspm_support_enabled(void) { return false; }
1573static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
1572#endif1574#endif
1573 1575
1574#ifdef CONFIG_PCIEAER1576#ifdef CONFIG_PCIEAER
kernel/sched/cpufreq_schedutil.c+10−4
@@ -40,6 +40,7 @@ struct sugov_policy { · 39 unmodified lines
40 struct task_struct *thread;40 struct task_struct *thread;
41 bool work_in_progress;41 bool work_in_progress;
42 42
43 bool limits_changed;
43 bool need_freq_update;44 bool need_freq_update;
44};45};
45 46
@@ -89,8 +90,11 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) · 43 unmodified lines
89 !cpufreq_this_cpu_can_update(sg_policy->policy))90 !cpufreq_this_cpu_can_update(sg_policy->policy))
90 return false;91 return false;
91 92
92 if (unlikely(sg_policy->need_freq_update))93 if (unlikely(sg_policy->limits_changed)) {
94 sg_policy->limits_changed = false;
95 sg_policy->need_freq_update = true;
93 return true;96 return true;
97 }
94 98
95 delta_ns = time - sg_policy->last_freq_update_time;99 delta_ns = time - sg_policy->last_freq_update_time;
96 100
@@ -437,7 +441,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } · 340 unmodified lines
437static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)441static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
438{442{
439 if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)443 if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
440 sg_policy->need_freq_update = true;444 sg_policy->limits_changed = true;
441}445}
442 446
443static void sugov_update_single(struct update_util_data *hook, u64 time,447static void sugov_update_single(struct update_util_data *hook, u64 time,
@@ -457,7 +461,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, · 13 unmodified lines
457 if (!sugov_should_update_freq(sg_policy, time))461 if (!sugov_should_update_freq(sg_policy, time))
458 return;462 return;
459 463
460 busy = sugov_cpu_is_busy(sg_cpu);464 /* Limits may have changed, don't skip frequency update */
465 busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
461 466
462 util = sugov_get_util(sg_cpu);467 util = sugov_get_util(sg_cpu);
463 max = sg_cpu->max;468 max = sg_cpu->max;
@@ -831,6 +836,7 @@ static int sugov_start(struct cpufreq_policy *policy) · 367 unmodified lines
831 sg_policy->last_freq_update_time = 0;836 sg_policy->last_freq_update_time = 0;
832 sg_policy->next_freq = 0;837 sg_policy->next_freq = 0;
833 sg_policy->work_in_progress = false;838 sg_policy->work_in_progress = false;
839 sg_policy->limits_changed = false;
834 sg_policy->need_freq_update = false;840 sg_policy->need_freq_update = false;
835 sg_policy->cached_raw_freq = 0;841 sg_policy->cached_raw_freq = 0;
836 842
@@ -879,7 +885,7 @@ static void sugov_limits(struct cpufreq_policy *policy) · 42 unmodified lines
879 mutex_unlock(&sg_policy->work_lock);885 mutex_unlock(&sg_policy->work_lock);
880 }886 }
881 887
882 sg_policy->need_freq_update = true;888 sg_policy->limits_changed = true;
883}889}
884 890
885struct cpufreq_governor schedutil_gov = {891struct cpufreq_governor schedutil_gov = {