Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+43 -8
+1 -1
drivers/cpufreq/cpufreq.c
··· 2528 2528 } 2529 2529 2530 2530 ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max); 2531 - if (ret) 2531 + if (ret < 0) 2532 2532 break; 2533 2533 } 2534 2534
+10 -3
drivers/nvme/host/pci.c
··· 2846 2846 struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev)); 2847 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 2850 nvme_set_power_state(ctrl, ndev->last_ps) != 0) 2851 2851 nvme_reset_ctrl(ctrl); 2852 2852 return 0; ··· 2859 2859 struct nvme_ctrl *ctrl = &ndev->ctrl; 2860 2860 int ret = -EBUSY; 2861 2861 2862 + ndev->last_ps = U32_MAX; 2863 + 2862 2864 /* 2863 2865 * The platform does not remove power for a kernel managed suspend so 2864 2866 * use host managed nvme power settings for lowest idle power if ··· 2868 2866 * shutdown. But if the firmware is involved after the suspend or the 2869 2867 * device does not support any non-default power states, shut down the 2870 2868 * device fully. 2869 + * 2870 + * If ASPM is not enabled for the device, shut down the device and allow 2871 + * the PCI bus layer to put it into D3 in order to take the PCIe link 2872 + * down, so as to allow the platform to achieve its minimum low-power 2873 + * state (which may not be possible if the link is up). 2871 2874 */ 2872 - if (pm_suspend_via_firmware() || !ctrl->npss) { 2875 + if (pm_suspend_via_firmware() || !ctrl->npss || 2876 + !pcie_aspm_enabled(pdev)) { 2873 2877 nvme_dev_disable(ndev, true); 2874 2878 return 0; 2875 2879 } ··· 2888 2880 ctrl->state != NVME_CTRL_ADMIN_ONLY) 2889 2881 goto unfreeze; 2890 2882 2891 - ndev->last_ps = 0; 2892 2883 ret = nvme_get_power_state(ctrl, &ndev->last_ps); 2893 2884 if (ret < 0) 2894 2885 goto unfreeze;
+20
drivers/pci/pcie/aspm.c
··· 1170 1170 module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy, 1171 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 + */ 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 + 1173 1193 #ifdef CONFIG_PCIEASPM_DEBUG 1174 1194 static ssize_t link_state_show(struct device *dev, 1175 1195 struct device_attribute *attr,
+2
include/linux/pci.h
··· 1567 1567 1568 1568 #ifdef CONFIG_PCIEASPM 1569 1569 bool pcie_aspm_support_enabled(void); 1570 + bool pcie_aspm_enabled(struct pci_dev *pdev); 1570 1571 #else 1571 1572 static inline bool pcie_aspm_support_enabled(void) { return false; } 1573 + static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; } 1572 1574 #endif 1573 1575 1574 1576 #ifdef CONFIG_PCIEAER
+10 -4
kernel/sched/cpufreq_schedutil.c
··· 40 40 struct task_struct *thread; 41 41 bool work_in_progress; 42 42 43 + bool limits_changed; 43 44 bool need_freq_update; 44 45 }; 45 46 ··· 90 89 !cpufreq_this_cpu_can_update(sg_policy->policy)) 91 90 return false; 92 91 93 - if (unlikely(sg_policy->need_freq_update)) 92 + if (unlikely(sg_policy->limits_changed)) { 93 + sg_policy->limits_changed = false; 94 + sg_policy->need_freq_update = true; 94 95 return true; 96 + } 95 97 96 98 delta_ns = time - sg_policy->last_freq_update_time; 97 99 ··· 441 437 static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy) 442 438 { 443 439 if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) 444 - sg_policy->need_freq_update = true; 440 + sg_policy->limits_changed = true; 445 441 } 446 442 447 443 static void sugov_update_single(struct update_util_data *hook, u64 time, ··· 461 457 if (!sugov_should_update_freq(sg_policy, time)) 462 458 return; 463 459 464 - busy = sugov_cpu_is_busy(sg_cpu); 460 + /* Limits may have changed, don't skip frequency update */ 461 + busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu); 465 462 466 463 util = sugov_get_util(sg_cpu); 467 464 max = sg_cpu->max; ··· 836 831 sg_policy->last_freq_update_time = 0; 837 832 sg_policy->next_freq = 0; 838 833 sg_policy->work_in_progress = false; 834 + sg_policy->limits_changed = false; 839 835 sg_policy->need_freq_update = false; 840 836 sg_policy->cached_raw_freq = 0; 841 837 ··· 885 879 mutex_unlock(&sg_policy->work_lock); 886 880 } 887 881 888 - sg_policy->need_freq_update = true; 882 + sg_policy->limits_changed = true; 889 883 } 890 884 891 885 struct cpufreq_governor schedutil_gov = {