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-6.8-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
"These restore the asynchronous device resume optimization removed by
the previous PM merge, make the intel_pstate driver work better on
Meteor Lake systems, optimize the PM QoS core code slightly and fix up
typos in admin-guide.

Specifics:

- Restore the system-wide asynchronous device resume optimization
removed by a recent concurrency fix (Rafael J. Wysocki)

- Make the intel_pstate cpufreq driver allow Meteor Lake systems to
run at somewhat higher frequencies (Srinivas Pandruvada)

- Make the PM QoS core code use kcalloc() for array allocation (Erick
Archer)

- Fix two PM-related typos in admin-guide (Erwan Velu)"

* tag 'pm-6.8-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM: sleep: Restore asynchronous device resume optimization
Documentation: admin-guide: PM: Fix two typos
cpufreq: intel_pstate: Update hybrid scaling factor for Meteor Lake
PM: QoS: Use kcalloc() instead of kzalloc()

+86 -59
+1 -1
Documentation/admin-guide/acpi/cppc_sysfs.rst
··· 75 75 delivered_counter_delta = fbc_t2[del] - fbc_t1[del] 76 76 reference_counter_delta = fbc_t2[ref] - fbc_t1[ref] 77 77 78 - delivered_perf = (refernce_perf x delivered_counter_delta) / reference_counter_delta 78 + delivered_perf = (reference_perf x delivered_counter_delta) / reference_counter_delta
+1 -1
Documentation/admin-guide/pm/amd-pstate.rst
··· 361 361 362 362 ``amd-pstate`` exposes several global attributes (files) in ``sysfs`` to 363 363 control its functionality at the system level. They are located in the 364 - ``/sys/devices/system/cpu/amd-pstate/`` directory and affect all CPUs. 364 + ``/sys/devices/system/cpu/amd_pstate/`` directory and affect all CPUs. 365 365 366 366 ``status`` 367 367 Operation mode of the driver: "active", "passive" or "disable".
+64 -53
drivers/base/power/main.c
··· 579 579 } 580 580 581 581 /** 582 - * __device_resume_noirq - Execute a "noirq resume" callback for given device. 582 + * device_resume_noirq - Execute a "noirq resume" callback for given device. 583 583 * @dev: Device to handle. 584 584 * @state: PM transition of the system being carried out. 585 585 * @async: If true, the device is being resumed asynchronously. ··· 587 587 * The driver of @dev will not receive interrupts while this function is being 588 588 * executed. 589 589 */ 590 - static void __device_resume_noirq(struct device *dev, pm_message_t state, bool async) 590 + static void device_resume_noirq(struct device *dev, pm_message_t state, bool async) 591 591 { 592 592 pm_callback_t callback = NULL; 593 593 const char *info = NULL; ··· 674 674 { 675 675 reinit_completion(&dev->power.completion); 676 676 677 - if (!is_async(dev)) 678 - return false; 677 + if (is_async(dev)) { 678 + dev->power.async_in_progress = true; 679 679 680 - get_device(dev); 680 + get_device(dev); 681 681 682 - if (async_schedule_dev_nocall(func, dev)) 683 - return true; 682 + if (async_schedule_dev_nocall(func, dev)) 683 + return true; 684 684 685 - put_device(dev); 686 - 685 + put_device(dev); 686 + } 687 + /* 688 + * Because async_schedule_dev_nocall() above has returned false or it 689 + * has not been called at all, func() is not running and it is safe to 690 + * update the async_in_progress flag without extra synchronization. 691 + */ 692 + dev->power.async_in_progress = false; 687 693 return false; 688 694 } 689 695 ··· 697 691 { 698 692 struct device *dev = data; 699 693 700 - __device_resume_noirq(dev, pm_transition, true); 694 + device_resume_noirq(dev, pm_transition, true); 701 695 put_device(dev); 702 - } 703 - 704 - static void device_resume_noirq(struct device *dev) 705 - { 706 - if (dpm_async_fn(dev, async_resume_noirq)) 707 - return; 708 - 709 - __device_resume_noirq(dev, pm_transition, false); 710 696 } 711 697 712 698 static void dpm_noirq_resume_devices(pm_message_t state) ··· 710 712 mutex_lock(&dpm_list_mtx); 711 713 pm_transition = state; 712 714 715 + /* 716 + * Trigger the resume of "async" devices upfront so they don't have to 717 + * wait for the "non-async" ones they don't depend on. 718 + */ 719 + list_for_each_entry(dev, &dpm_noirq_list, power.entry) 720 + dpm_async_fn(dev, async_resume_noirq); 721 + 713 722 while (!list_empty(&dpm_noirq_list)) { 714 723 dev = to_device(dpm_noirq_list.next); 715 - get_device(dev); 716 724 list_move_tail(&dev->power.entry, &dpm_late_early_list); 717 725 718 - mutex_unlock(&dpm_list_mtx); 726 + if (!dev->power.async_in_progress) { 727 + get_device(dev); 719 728 720 - device_resume_noirq(dev); 729 + mutex_unlock(&dpm_list_mtx); 721 730 722 - put_device(dev); 731 + device_resume_noirq(dev, state, false); 723 732 724 - mutex_lock(&dpm_list_mtx); 733 + put_device(dev); 734 + 735 + mutex_lock(&dpm_list_mtx); 736 + } 725 737 } 726 738 mutex_unlock(&dpm_list_mtx); 727 739 async_synchronize_full(); ··· 755 747 } 756 748 757 749 /** 758 - * __device_resume_early - Execute an "early resume" callback for given device. 750 + * device_resume_early - Execute an "early resume" callback for given device. 759 751 * @dev: Device to handle. 760 752 * @state: PM transition of the system being carried out. 761 753 * @async: If true, the device is being resumed asynchronously. 762 754 * 763 755 * Runtime PM is disabled for @dev while this function is being executed. 764 756 */ 765 - static void __device_resume_early(struct device *dev, pm_message_t state, bool async) 757 + static void device_resume_early(struct device *dev, pm_message_t state, bool async) 766 758 { 767 759 pm_callback_t callback = NULL; 768 760 const char *info = NULL; ··· 828 820 { 829 821 struct device *dev = data; 830 822 831 - __device_resume_early(dev, pm_transition, true); 823 + device_resume_early(dev, pm_transition, true); 832 824 put_device(dev); 833 - } 834 - 835 - static void device_resume_early(struct device *dev) 836 - { 837 - if (dpm_async_fn(dev, async_resume_early)) 838 - return; 839 - 840 - __device_resume_early(dev, pm_transition, false); 841 825 } 842 826 843 827 /** ··· 845 845 mutex_lock(&dpm_list_mtx); 846 846 pm_transition = state; 847 847 848 + /* 849 + * Trigger the resume of "async" devices upfront so they don't have to 850 + * wait for the "non-async" ones they don't depend on. 851 + */ 852 + list_for_each_entry(dev, &dpm_late_early_list, power.entry) 853 + dpm_async_fn(dev, async_resume_early); 854 + 848 855 while (!list_empty(&dpm_late_early_list)) { 849 856 dev = to_device(dpm_late_early_list.next); 850 - get_device(dev); 851 857 list_move_tail(&dev->power.entry, &dpm_suspended_list); 852 858 853 - mutex_unlock(&dpm_list_mtx); 859 + if (!dev->power.async_in_progress) { 860 + get_device(dev); 854 861 855 - device_resume_early(dev); 862 + mutex_unlock(&dpm_list_mtx); 856 863 857 - put_device(dev); 864 + device_resume_early(dev, state, false); 858 865 859 - mutex_lock(&dpm_list_mtx); 866 + put_device(dev); 867 + 868 + mutex_lock(&dpm_list_mtx); 869 + } 860 870 } 861 871 mutex_unlock(&dpm_list_mtx); 862 872 async_synchronize_full(); ··· 886 876 EXPORT_SYMBOL_GPL(dpm_resume_start); 887 877 888 878 /** 889 - * __device_resume - Execute "resume" callbacks for given device. 879 + * device_resume - Execute "resume" callbacks for given device. 890 880 * @dev: Device to handle. 891 881 * @state: PM transition of the system being carried out. 892 882 * @async: If true, the device is being resumed asynchronously. 893 883 */ 894 - static void __device_resume(struct device *dev, pm_message_t state, bool async) 884 + static void device_resume(struct device *dev, pm_message_t state, bool async) 895 885 { 896 886 pm_callback_t callback = NULL; 897 887 const char *info = NULL; ··· 985 975 { 986 976 struct device *dev = data; 987 977 988 - __device_resume(dev, pm_transition, true); 978 + device_resume(dev, pm_transition, true); 989 979 put_device(dev); 990 - } 991 - 992 - static void device_resume(struct device *dev) 993 - { 994 - if (dpm_async_fn(dev, async_resume)) 995 - return; 996 - 997 - __device_resume(dev, pm_transition, false); 998 980 } 999 981 1000 982 /** ··· 1008 1006 pm_transition = state; 1009 1007 async_error = 0; 1010 1008 1009 + /* 1010 + * Trigger the resume of "async" devices upfront so they don't have to 1011 + * wait for the "non-async" ones they don't depend on. 1012 + */ 1013 + list_for_each_entry(dev, &dpm_suspended_list, power.entry) 1014 + dpm_async_fn(dev, async_resume); 1015 + 1011 1016 while (!list_empty(&dpm_suspended_list)) { 1012 1017 dev = to_device(dpm_suspended_list.next); 1013 1018 1014 1019 get_device(dev); 1015 1020 1016 - mutex_unlock(&dpm_list_mtx); 1021 + if (!dev->power.async_in_progress) { 1022 + mutex_unlock(&dpm_list_mtx); 1017 1023 1018 - device_resume(dev); 1024 + device_resume(dev, state, false); 1019 1025 1020 - mutex_lock(&dpm_list_mtx); 1026 + mutex_lock(&dpm_list_mtx); 1027 + } 1021 1028 1022 1029 if (!list_empty(&dev->power.entry)) 1023 1030 list_move_tail(&dev->power.entry, &dpm_prepared_list);
+1 -1
drivers/base/power/qos.c
··· 201 201 if (!qos) 202 202 return -ENOMEM; 203 203 204 - n = kzalloc(3 * sizeof(*n), GFP_KERNEL); 204 + n = kcalloc(3, sizeof(*n), GFP_KERNEL); 205 205 if (!n) { 206 206 kfree(qos); 207 207 return -ENOMEM;
+18 -3
drivers/cpufreq/intel_pstate.c
··· 302 302 303 303 static struct cpufreq_driver *intel_pstate_driver __read_mostly; 304 304 305 - #define HYBRID_SCALING_FACTOR 78741 305 + #define HYBRID_SCALING_FACTOR 78741 306 + #define HYBRID_SCALING_FACTOR_MTL 80000 307 + 308 + static int hybrid_scaling_factor = HYBRID_SCALING_FACTOR; 306 309 307 310 static inline int core_get_scaling(void) 308 311 { ··· 425 422 */ 426 423 if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq && 427 424 cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq) 428 - return HYBRID_SCALING_FACTOR; 425 + return hybrid_scaling_factor; 429 426 430 427 return core_get_scaling(); 431 428 } ··· 1971 1968 smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); 1972 1969 /* P-cores have a smaller perf level-to-freqency scaling factor. */ 1973 1970 if (cpu_type == 0x40) 1974 - return HYBRID_SCALING_FACTOR; 1971 + return hybrid_scaling_factor; 1975 1972 1976 1973 /* Use default core scaling for E-cores */ 1977 1974 if (cpu_type == 0x20) ··· 3402 3399 {} 3403 3400 }; 3404 3401 3402 + static const struct x86_cpu_id intel_hybrid_scaling_factor[] = { 3403 + X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, HYBRID_SCALING_FACTOR_MTL), 3404 + {} 3405 + }; 3406 + 3405 3407 static int __init intel_pstate_init(void) 3406 3408 { 3407 3409 static struct cpudata **_all_cpu_data; ··· 3497 3489 3498 3490 if (hwp_active) { 3499 3491 const struct x86_cpu_id *id = x86_match_cpu(intel_epp_balance_perf); 3492 + const struct x86_cpu_id *hybrid_id = x86_match_cpu(intel_hybrid_scaling_factor); 3500 3493 3501 3494 if (id) 3502 3495 epp_values[EPP_INDEX_BALANCE_PERFORMANCE] = id->driver_data; 3496 + 3497 + if (hybrid_id) { 3498 + hybrid_scaling_factor = hybrid_id->driver_data; 3499 + pr_debug("hybrid scaling factor: %d\n", hybrid_scaling_factor); 3500 + } 3501 + 3503 3502 } 3504 3503 3505 3504 mutex_lock(&intel_pstate_driver_lock);
+1
include/linux/pm.h
··· 681 681 bool wakeup_path:1; 682 682 bool syscore:1; 683 683 bool no_pm_callbacks:1; /* Owned by the PM core */ 684 + bool async_in_progress:1; /* Owned by the PM core */ 684 685 unsigned int must_resume:1; /* Owned by the PM core */ 685 686 unsigned int may_skip_resume:1; /* Set by subsystems */ 686 687 #else