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

Pull power management fixes from Rafael Wysocki:
"These fix up recent intel_idle driver changes and fix some ARM cpufreq
driver issues.

Specifics:

- Fix issues with the Qualcomm's cpufreq driver (Dmitry Baryshkov,
Vladimir Zapolskiy).

- Fix memory leak with the Sun501 driver (Xiaobing Luo).

- Make intel_idle enable C1E promotion on all CPUs when C1E is
preferred to C1 (Artem Bityutskiy).

- Make C6 optimization on Sapphire Rapids added recently work as
expected if both C1E and C1 are "preferred" (Artem Bityutskiy)"

* tag 'pm-5.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
intel_idle: Fix SPR C6 optimization
intel_idle: Fix the 'preferred_cstates' module parameter
cpufreq: qcom-cpufreq-hw: Clear dcvs interrupts
cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe
cpufreq: qcom-cpufreq-hw: Fix throttle frequency value on EPSS platforms
cpufreq: qcom-hw: provide online/offline operations
cpufreq: qcom-hw: fix the opp entries refcounting
cpufreq: qcom-hw: fix the race between LMH worker and cpuhp
cpufreq: qcom-hw: drop affinity hint before freeing the IRQ

+75 -26
+57 -13
drivers/cpufreq/qcom-cpufreq-hw.c
··· 24 24 #define CLK_HW_DIV 2 25 25 #define LUT_TURBO_IND 1 26 26 27 + #define GT_IRQ_STATUS BIT(2) 28 + 27 29 #define HZ_PER_KHZ 1000 28 30 29 31 struct qcom_cpufreq_soc_data { 30 32 u32 reg_enable; 33 + u32 reg_domain_state; 31 34 u32 reg_dcvs_ctrl; 32 35 u32 reg_freq_lut; 33 36 u32 reg_volt_lut; 37 + u32 reg_intr_clr; 34 38 u32 reg_current_vote; 35 39 u32 reg_perf_state; 36 40 u8 lut_row_size; ··· 284 280 } 285 281 } 286 282 287 - static unsigned int qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) 283 + static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) 288 284 { 289 - unsigned int val = readl_relaxed(data->base + data->soc_data->reg_current_vote); 285 + unsigned int lval; 290 286 291 - return (val & 0x3FF) * 19200; 287 + if (data->soc_data->reg_current_vote) 288 + lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff; 289 + else 290 + lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff; 291 + 292 + return lval * xo_rate; 292 293 } 293 294 294 295 static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) 295 296 { 296 297 struct cpufreq_policy *policy = data->policy; 297 - int cpu = cpumask_first(policy->cpus); 298 + int cpu = cpumask_first(policy->related_cpus); 298 299 struct device *dev = get_cpu_device(cpu); 299 300 unsigned long freq_hz, throttled_freq; 300 301 struct dev_pm_opp *opp; 301 - unsigned int freq; 302 302 303 303 /* 304 304 * Get the h/w throttled frequency, normalize it using the 305 305 * registered opp table and use it to calculate thermal pressure. 306 306 */ 307 - freq = qcom_lmh_get_throttle_freq(data); 308 - freq_hz = freq * HZ_PER_KHZ; 307 + freq_hz = qcom_lmh_get_throttle_freq(data); 309 308 310 309 opp = dev_pm_opp_find_freq_floor(dev, &freq_hz); 311 310 if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) 312 - dev_pm_opp_find_freq_ceil(dev, &freq_hz); 311 + opp = dev_pm_opp_find_freq_ceil(dev, &freq_hz); 313 312 314 - throttled_freq = freq_hz / HZ_PER_KHZ; 313 + if (IS_ERR(opp)) { 314 + dev_warn(dev, "Can't find the OPP for throttling: %pe!\n", opp); 315 + } else { 316 + throttled_freq = freq_hz / HZ_PER_KHZ; 315 317 316 - /* Update thermal pressure (the boost frequencies are accepted) */ 317 - arch_update_thermal_pressure(policy->related_cpus, throttled_freq); 318 + /* Update thermal pressure (the boost frequencies are accepted) */ 319 + arch_update_thermal_pressure(policy->related_cpus, throttled_freq); 320 + 321 + dev_pm_opp_put(opp); 322 + } 318 323 319 324 /* 320 325 * In the unlikely case policy is unregistered do not enable ··· 363 350 disable_irq_nosync(c_data->throttle_irq); 364 351 schedule_delayed_work(&c_data->throttle_work, 0); 365 352 353 + if (c_data->soc_data->reg_intr_clr) 354 + writel_relaxed(GT_IRQ_STATUS, 355 + c_data->base + c_data->soc_data->reg_intr_clr); 356 + 366 357 return IRQ_HANDLED; 367 358 } 368 359 ··· 382 365 383 366 static const struct qcom_cpufreq_soc_data epss_soc_data = { 384 367 .reg_enable = 0x0, 368 + .reg_domain_state = 0x20, 385 369 .reg_dcvs_ctrl = 0xb0, 386 370 .reg_freq_lut = 0x100, 387 371 .reg_volt_lut = 0x200, 372 + .reg_intr_clr = 0x308, 388 373 .reg_perf_state = 0x320, 389 374 .lut_row_size = 4, 390 375 }; ··· 436 417 return 0; 437 418 } 438 419 439 - static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data) 420 + static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy) 440 421 { 422 + struct qcom_cpufreq_data *data = policy->driver_data; 423 + struct platform_device *pdev = cpufreq_get_driver_data(); 424 + int ret; 425 + 426 + ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus); 427 + if (ret) 428 + dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n", 429 + data->irq_name, data->throttle_irq); 430 + 431 + return ret; 432 + } 433 + 434 + static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy) 435 + { 436 + struct qcom_cpufreq_data *data = policy->driver_data; 437 + 441 438 if (data->throttle_irq <= 0) 442 - return; 439 + return 0; 443 440 444 441 mutex_lock(&data->throttle_lock); 445 442 data->cancel_throttle = true; 446 443 mutex_unlock(&data->throttle_lock); 447 444 448 445 cancel_delayed_work_sync(&data->throttle_work); 446 + irq_set_affinity_hint(data->throttle_irq, NULL); 447 + 448 + return 0; 449 + } 450 + 451 + static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data) 452 + { 449 453 free_irq(data->throttle_irq, data); 450 454 } 451 455 ··· 625 583 .get = qcom_cpufreq_hw_get, 626 584 .init = qcom_cpufreq_hw_cpu_init, 627 585 .exit = qcom_cpufreq_hw_cpu_exit, 586 + .online = qcom_cpufreq_hw_cpu_online, 587 + .offline = qcom_cpufreq_hw_cpu_offline, 628 588 .register_em = cpufreq_register_em_with_opp, 629 589 .fast_switch = qcom_cpufreq_hw_fast_switch, 630 590 .name = "qcom-cpufreq-hw",
+3 -1
drivers/cpufreq/sun50i-cpufreq-nvmem.c
··· 98 98 return -ENOMEM; 99 99 100 100 ret = sun50i_cpufreq_get_efuse(&speed); 101 - if (ret) 101 + if (ret) { 102 + kfree(opp_tables); 102 103 return ret; 104 + } 103 105 104 106 snprintf(name, MAX_NAME_LEN, "speed%d", speed); 105 107
+15 -12
drivers/idle/intel_idle.c
··· 69 69 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; 70 70 71 71 static unsigned long auto_demotion_disable_flags; 72 - static bool disable_promotion_to_c1e; 72 + 73 + static enum { 74 + C1E_PROMOTION_PRESERVE, 75 + C1E_PROMOTION_ENABLE, 76 + C1E_PROMOTION_DISABLE 77 + } c1e_promotion = C1E_PROMOTION_PRESERVE; 73 78 74 79 struct idle_cpu { 75 80 struct cpuidle_state *state_table; ··· 1403 1398 static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; } 1404 1399 #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */ 1405 1400 1406 - static void c1e_promotion_enable(void); 1407 - 1408 1401 /** 1409 1402 * ivt_idle_state_table_update - Tune the idle states table for Ivy Town. 1410 1403 * ··· 1581 1578 unsigned long long msr; 1582 1579 1583 1580 /* Check if user prefers C1E over C1. */ 1584 - if (preferred_states_mask & BIT(2)) { 1585 - if (preferred_states_mask & BIT(1)) 1586 - /* Both can't be enabled, stick to the defaults. */ 1587 - return; 1588 - 1581 + if ((preferred_states_mask & BIT(2)) && 1582 + !(preferred_states_mask & BIT(1))) { 1583 + /* Disable C1 and enable C1E. */ 1589 1584 spr_cstates[0].flags |= CPUIDLE_FLAG_UNUSABLE; 1590 1585 spr_cstates[1].flags &= ~CPUIDLE_FLAG_UNUSABLE; 1591 1586 1592 1587 /* Enable C1E using the "C1E promotion" bit. */ 1593 - c1e_promotion_enable(); 1594 - disable_promotion_to_c1e = false; 1588 + c1e_promotion = C1E_PROMOTION_ENABLE; 1595 1589 } 1596 1590 1597 1591 /* ··· 1754 1754 if (auto_demotion_disable_flags) 1755 1755 auto_demotion_disable(); 1756 1756 1757 - if (disable_promotion_to_c1e) 1757 + if (c1e_promotion == C1E_PROMOTION_ENABLE) 1758 + c1e_promotion_enable(); 1759 + else if (c1e_promotion == C1E_PROMOTION_DISABLE) 1758 1760 c1e_promotion_disable(); 1759 1761 1760 1762 return 0; ··· 1835 1833 if (icpu) { 1836 1834 cpuidle_state_table = icpu->state_table; 1837 1835 auto_demotion_disable_flags = icpu->auto_demotion_disable_flags; 1838 - disable_promotion_to_c1e = icpu->disable_promotion_to_c1e; 1836 + if (icpu->disable_promotion_to_c1e) 1837 + c1e_promotion = C1E_PROMOTION_DISABLE; 1839 1838 if (icpu->use_acpi || force_use_acpi) 1840 1839 intel_idle_acpi_cst_extract(); 1841 1840 } else if (!intel_idle_acpi_cst_extract()) {