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
25282528 }
25292529
25302530 ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
2531− if (ret)
2531+ if (ret < 0)
25322532 break;
25332533 }
25342534
drivers/nvme/host/pci.c+10−3
@@ -2846,7 +2846,7 @@ static int nvme_resume(struct device *dev) · 2845 unmodified lines
28462846 struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
28472847 struct nvme_ctrl *ctrl = &ndev->ctrl;
28482848
2849− if (pm_resume_via_firmware() || !ctrl->npss ||
2849+ if (ndev->last_ps == U32_MAX ||
28502850 nvme_set_power_state(ctrl, ndev->last_ps) != 0)
28512851 nvme_reset_ctrl(ctrl);
28522852 return 0;
@@ -2859,6 +2859,8 @@ static int nvme_suspend(struct device *dev) · 6 unmodified lines
28592859 struct nvme_ctrl *ctrl = &ndev->ctrl;
28602860 int ret = -EBUSY;
28612861
2862+ ndev->last_ps = U32_MAX;
2863+
28622864 /*
28632865 * The platform does not remove power for a kernel managed suspend so
28642866 * 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
28662868 * shutdown. But if the firmware is involved after the suspend or the
28672869 * device does not support any non-default power states, shut down the
28682870 * 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).
28692876 */
2870− if (pm_suspend_via_firmware() || !ctrl->npss) {
2877+ if (pm_suspend_via_firmware() || !ctrl->npss ||
2878+ !pcie_aspm_enabled(pdev)) {
28712879 nvme_dev_disable(ndev, true);
28722880 return 0;
28732881 }
@@ -2880,7 +2888,6 @@ static int nvme_suspend(struct device *dev) · 6 unmodified lines
28802888 ctrl->state != NVME_CTRL_ADMIN_ONLY)
28812889 goto unfreeze;
28822890
2883− ndev->last_ps = 0;
28842891 ret = nvme_get_power_state(ctrl, &ndev->last_ps);
28852892 if (ret < 0)
28862893 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
11701170 module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
11711171 NULL, 0644);
11721172
1173+/**
1174+ * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
1175+ * @pdev: Target device.
1176+ */
1177+bool 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+}
1191+EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
1192+
11731193 #ifdef CONFIG_PCIEASPM_DEBUG
11741194 static ssize_t link_state_show(struct device *dev,
11751195 struct device_attribute *attr,
include/linux/pci.h+2−0
@@ -1567,8 +1567,10 @@ extern bool pcie_ports_native; · 1566 unmodified lines
15671567
15681568 #ifdef CONFIG_PCIEASPM
15691569 bool pcie_aspm_support_enabled(void);
1570+bool pcie_aspm_enabled(struct pci_dev *pdev);
15701571 #else
15711572 static inline bool pcie_aspm_support_enabled(void) { return false; }
1573+static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
15721574 #endif
15731575
15741576 #ifdef CONFIG_PCIEAER
kernel/sched/cpufreq_schedutil.c+10−4
@@ -40,6 +40,7 @@ struct sugov_policy { · 39 unmodified lines
4040 struct task_struct *thread;
4141 bool work_in_progress;
4242
43+ bool limits_changed;
4344 bool need_freq_update;
4445 };
4546
@@ -89,8 +90,11 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) · 43 unmodified lines
8990 !cpufreq_this_cpu_can_update(sg_policy->policy))
9091 return false;
9192
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;
9396 return true;
97+ }
9498
9599 delta_ns = time - sg_policy->last_freq_update_time;
96100
@@ -437,7 +441,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } · 340 unmodified lines
437441 static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
438442 {
439443 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;
441445 }
442446
443447 static 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
457461 if (!sugov_should_update_freq(sg_policy, time))
458462 return;
459463
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);
461466
462467 util = sugov_get_util(sg_cpu);
463468 max = sg_cpu->max;
@@ -831,6 +836,7 @@ static int sugov_start(struct cpufreq_policy *policy) · 367 unmodified lines
831836 sg_policy->last_freq_update_time = 0;
832837 sg_policy->next_freq = 0;
833838 sg_policy->work_in_progress = false;
839+ sg_policy->limits_changed = false;
834840 sg_policy->need_freq_update = false;
835841 sg_policy->cached_raw_freq = 0;
836842
@@ -879,7 +885,7 @@ static void sugov_limits(struct cpufreq_policy *policy) · 42 unmodified lines
879885 mutex_unlock(&sg_policy->work_lock);
880886 }
881887
882− sg_policy->need_freq_update = true;
888+ sg_policy->limits_changed = true;
883889 }
884890
885891 struct cpufreq_governor schedutil_gov = {