diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-06-13 05:04:16 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-06-13 05:04:16 -0400 |
commit | 2652df3af7317ebd88cd4493a0683e52d5199694 (patch) | |
tree | ec98d2ebad43c3467e449900eb33646d0e8948ad | |
parent | b06c0b2f087ab498d51d50f5ae353133b602f614 (diff) | |
parent | 0aa9abd4c212fc1cd111cc0a9fc571f0d86e63cf (diff) |
Merge branch 'pm-cpufreq'
Additional cpufreq updates for 4.18-rc1: fixes and cleanups in the
core and drivers and intel_pstate extension to do iowait boosting
on systems with HWP that improves performance quite a bit.
* pm-cpufreq:
cpufreq: imx6q: check speed grades for i.MX6ULL
cpufreq: governors: Fix long idle detection logic in load calculation
cpufreq: intel_pstate: enable boost for Skylake Xeon
cpufreq: intel_pstate: New sysfs entry to control HWP boost
cpufreq: intel_pstate: HWP boost performance on IO wakeup
cpufreq: intel_pstate: Add HWP boost utility and sched util hooks
cpufreq: ti-cpufreq: Use devres managed API in probe()
cpufreq: ti-cpufreq: Fix an incorrect error return value
cpufreq: ACPI: make function acpi_cpufreq_fast_switch() static
cpufreq: kryo: allow building as a loadable module
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 2 | ||||
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 4 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 12 | ||||
-rw-r--r-- | drivers/cpufreq/imx6q-cpufreq.c | 29 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 179 | ||||
-rw-r--r-- | drivers/cpufreq/ti-cpufreq.c | 7 |
6 files changed, 209 insertions, 24 deletions
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index c7ce928fbf1f..52f5f1a2040c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -125,7 +125,7 @@ config ARM_OMAP2PLUS_CPUFREQ | |||
125 | default ARCH_OMAP2PLUS | 125 | default ARCH_OMAP2PLUS |
126 | 126 | ||
127 | config ARM_QCOM_CPUFREQ_KRYO | 127 | config ARM_QCOM_CPUFREQ_KRYO |
128 | bool "Qualcomm Kryo based CPUFreq" | 128 | tristate "Qualcomm Kryo based CPUFreq" |
129 | depends on ARM64 | 129 | depends on ARM64 |
130 | depends on QCOM_QFPROM | 130 | depends on QCOM_QFPROM |
131 | depends on QCOM_SMEM | 131 | depends on QCOM_SMEM |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 9449657d72f0..32ba4bc972e7 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -465,8 +465,8 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, | |||
465 | return result; | 465 | return result; |
466 | } | 466 | } |
467 | 467 | ||
468 | unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, | 468 | static unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, |
469 | unsigned int target_freq) | 469 | unsigned int target_freq) |
470 | { | 470 | { |
471 | struct acpi_cpufreq_data *data = policy->driver_data; | 471 | struct acpi_cpufreq_data *data = policy->driver_data; |
472 | struct acpi_processor_performance *perf; | 472 | struct acpi_processor_performance *perf; |
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 871bf9cf55cf..1d50e97d49f1 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c | |||
@@ -165,7 +165,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy) | |||
165 | * calls, so the previous load value can be used then. | 165 | * calls, so the previous load value can be used then. |
166 | */ | 166 | */ |
167 | load = j_cdbs->prev_load; | 167 | load = j_cdbs->prev_load; |
168 | } else if (unlikely(time_elapsed > 2 * sampling_rate && | 168 | } else if (unlikely((int)idle_time > 2 * sampling_rate && |
169 | j_cdbs->prev_load)) { | 169 | j_cdbs->prev_load)) { |
170 | /* | 170 | /* |
171 | * If the CPU had gone completely idle and a task has | 171 | * If the CPU had gone completely idle and a task has |
@@ -185,10 +185,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy) | |||
185 | * clear prev_load to guarantee that the load will be | 185 | * clear prev_load to guarantee that the load will be |
186 | * computed again next time. | 186 | * computed again next time. |
187 | * | 187 | * |
188 | * Detecting this situation is easy: the governor's | 188 | * Detecting this situation is easy: an unusually large |
189 | * utilization update handler would not have run during | 189 | * 'idle_time' (as compared to the sampling rate) |
190 | * CPU-idle periods. Hence, an unusually large | ||
191 | * 'time_elapsed' (as compared to the sampling rate) | ||
192 | * indicates this scenario. | 190 | * indicates this scenario. |
193 | */ | 191 | */ |
194 | load = j_cdbs->prev_load; | 192 | load = j_cdbs->prev_load; |
@@ -217,8 +215,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy) | |||
217 | j_cdbs->prev_load = load; | 215 | j_cdbs->prev_load = load; |
218 | } | 216 | } |
219 | 217 | ||
220 | if (time_elapsed > 2 * sampling_rate) { | 218 | if (unlikely((int)idle_time > 2 * sampling_rate)) { |
221 | unsigned int periods = time_elapsed / sampling_rate; | 219 | unsigned int periods = idle_time / sampling_rate; |
222 | 220 | ||
223 | if (periods < idle_periods) | 221 | if (periods < idle_periods) |
224 | idle_periods = periods; | 222 | idle_periods = periods; |
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 83cf631fc9bc..f094687cae52 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c | |||
@@ -266,6 +266,8 @@ put_node: | |||
266 | } | 266 | } |
267 | 267 | ||
268 | #define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2 | 268 | #define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2 |
269 | #define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2 | ||
270 | #define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3 | ||
269 | 271 | ||
270 | static void imx6ul_opp_check_speed_grading(struct device *dev) | 272 | static void imx6ul_opp_check_speed_grading(struct device *dev) |
271 | { | 273 | { |
@@ -287,16 +289,30 @@ static void imx6ul_opp_check_speed_grading(struct device *dev) | |||
287 | * Speed GRADING[1:0] defines the max speed of ARM: | 289 | * Speed GRADING[1:0] defines the max speed of ARM: |
288 | * 2b'00: Reserved; | 290 | * 2b'00: Reserved; |
289 | * 2b'01: 528000000Hz; | 291 | * 2b'01: 528000000Hz; |
290 | * 2b'10: 696000000Hz; | 292 | * 2b'10: 696000000Hz on i.MX6UL, 792000000Hz on i.MX6ULL; |
291 | * 2b'11: Reserved; | 293 | * 2b'11: 900000000Hz on i.MX6ULL only; |
292 | * We need to set the max speed of ARM according to fuse map. | 294 | * We need to set the max speed of ARM according to fuse map. |
293 | */ | 295 | */ |
294 | val = readl_relaxed(base + OCOTP_CFG3); | 296 | val = readl_relaxed(base + OCOTP_CFG3); |
295 | val >>= OCOTP_CFG3_SPEED_SHIFT; | 297 | val >>= OCOTP_CFG3_SPEED_SHIFT; |
296 | val &= 0x3; | 298 | val &= 0x3; |
297 | if (val != OCOTP_CFG3_6UL_SPEED_696MHZ) | 299 | |
298 | if (dev_pm_opp_disable(dev, 696000000)) | 300 | if (of_machine_is_compatible("fsl,imx6ul")) { |
299 | dev_warn(dev, "failed to disable 696MHz OPP\n"); | 301 | if (val != OCOTP_CFG3_6UL_SPEED_696MHZ) |
302 | if (dev_pm_opp_disable(dev, 696000000)) | ||
303 | dev_warn(dev, "failed to disable 696MHz OPP\n"); | ||
304 | } | ||
305 | |||
306 | if (of_machine_is_compatible("fsl,imx6ull")) { | ||
307 | if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ) | ||
308 | if (dev_pm_opp_disable(dev, 792000000)) | ||
309 | dev_warn(dev, "failed to disable 792MHz OPP\n"); | ||
310 | |||
311 | if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ) | ||
312 | if (dev_pm_opp_disable(dev, 900000000)) | ||
313 | dev_warn(dev, "failed to disable 900MHz OPP\n"); | ||
314 | } | ||
315 | |||
300 | iounmap(base); | 316 | iounmap(base); |
301 | put_node: | 317 | put_node: |
302 | of_node_put(np); | 318 | of_node_put(np); |
@@ -356,7 +372,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | |||
356 | goto put_reg; | 372 | goto put_reg; |
357 | } | 373 | } |
358 | 374 | ||
359 | if (of_machine_is_compatible("fsl,imx6ul")) | 375 | if (of_machine_is_compatible("fsl,imx6ul") || |
376 | of_machine_is_compatible("fsl,imx6ull")) | ||
360 | imx6ul_opp_check_speed_grading(cpu_dev); | 377 | imx6ul_opp_check_speed_grading(cpu_dev); |
361 | else | 378 | else |
362 | imx6q_opp_check_speed_grading(cpu_dev); | 379 | imx6q_opp_check_speed_grading(cpu_dev); |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 08960a55eb27..352d5b2d5b58 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -221,6 +221,11 @@ struct global_params { | |||
221 | * preference/bias | 221 | * preference/bias |
222 | * @epp_saved: Saved EPP/EPB during system suspend or CPU offline | 222 | * @epp_saved: Saved EPP/EPB during system suspend or CPU offline |
223 | * operation | 223 | * operation |
224 | * @hwp_req_cached: Cached value of the last HWP Request MSR | ||
225 | * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR | ||
226 | * @last_io_update: Last time when IO wake flag was set | ||
227 | * @sched_flags: Store scheduler flags for possible cross CPU update | ||
228 | * @hwp_boost_min: Last HWP boosted min performance | ||
224 | * | 229 | * |
225 | * This structure stores per CPU instance data for all CPUs. | 230 | * This structure stores per CPU instance data for all CPUs. |
226 | */ | 231 | */ |
@@ -253,6 +258,11 @@ struct cpudata { | |||
253 | s16 epp_policy; | 258 | s16 epp_policy; |
254 | s16 epp_default; | 259 | s16 epp_default; |
255 | s16 epp_saved; | 260 | s16 epp_saved; |
261 | u64 hwp_req_cached; | ||
262 | u64 hwp_cap_cached; | ||
263 | u64 last_io_update; | ||
264 | unsigned int sched_flags; | ||
265 | u32 hwp_boost_min; | ||
256 | }; | 266 | }; |
257 | 267 | ||
258 | static struct cpudata **all_cpu_data; | 268 | static struct cpudata **all_cpu_data; |
@@ -285,6 +295,7 @@ static struct pstate_funcs pstate_funcs __read_mostly; | |||
285 | 295 | ||
286 | static int hwp_active __read_mostly; | 296 | static int hwp_active __read_mostly; |
287 | static bool per_cpu_limits __read_mostly; | 297 | static bool per_cpu_limits __read_mostly; |
298 | static bool hwp_boost __read_mostly; | ||
288 | 299 | ||
289 | static struct cpufreq_driver *intel_pstate_driver __read_mostly; | 300 | static struct cpufreq_driver *intel_pstate_driver __read_mostly; |
290 | 301 | ||
@@ -689,6 +700,7 @@ static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max, | |||
689 | u64 cap; | 700 | u64 cap; |
690 | 701 | ||
691 | rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); | 702 | rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); |
703 | WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap); | ||
692 | if (global.no_turbo) | 704 | if (global.no_turbo) |
693 | *current_max = HWP_GUARANTEED_PERF(cap); | 705 | *current_max = HWP_GUARANTEED_PERF(cap); |
694 | else | 706 | else |
@@ -763,6 +775,7 @@ update_epp: | |||
763 | intel_pstate_set_epb(cpu, epp); | 775 | intel_pstate_set_epb(cpu, epp); |
764 | } | 776 | } |
765 | skip_epp: | 777 | skip_epp: |
778 | WRITE_ONCE(cpu_data->hwp_req_cached, value); | ||
766 | wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value); | 779 | wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value); |
767 | } | 780 | } |
768 | 781 | ||
@@ -1020,6 +1033,30 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
1020 | return count; | 1033 | return count; |
1021 | } | 1034 | } |
1022 | 1035 | ||
1036 | static ssize_t show_hwp_dynamic_boost(struct kobject *kobj, | ||
1037 | struct attribute *attr, char *buf) | ||
1038 | { | ||
1039 | return sprintf(buf, "%u\n", hwp_boost); | ||
1040 | } | ||
1041 | |||
1042 | static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute *b, | ||
1043 | const char *buf, size_t count) | ||
1044 | { | ||
1045 | unsigned int input; | ||
1046 | int ret; | ||
1047 | |||
1048 | ret = kstrtouint(buf, 10, &input); | ||
1049 | if (ret) | ||
1050 | return ret; | ||
1051 | |||
1052 | mutex_lock(&intel_pstate_driver_lock); | ||
1053 | hwp_boost = !!input; | ||
1054 | intel_pstate_update_policies(); | ||
1055 | mutex_unlock(&intel_pstate_driver_lock); | ||
1056 | |||
1057 | return count; | ||
1058 | } | ||
1059 | |||
1023 | show_one(max_perf_pct, max_perf_pct); | 1060 | show_one(max_perf_pct, max_perf_pct); |
1024 | show_one(min_perf_pct, min_perf_pct); | 1061 | show_one(min_perf_pct, min_perf_pct); |
1025 | 1062 | ||
@@ -1029,6 +1066,7 @@ define_one_global_rw(max_perf_pct); | |||
1029 | define_one_global_rw(min_perf_pct); | 1066 | define_one_global_rw(min_perf_pct); |
1030 | define_one_global_ro(turbo_pct); | 1067 | define_one_global_ro(turbo_pct); |
1031 | define_one_global_ro(num_pstates); | 1068 | define_one_global_ro(num_pstates); |
1069 | define_one_global_rw(hwp_dynamic_boost); | ||
1032 | 1070 | ||
1033 | static struct attribute *intel_pstate_attributes[] = { | 1071 | static struct attribute *intel_pstate_attributes[] = { |
1034 | &status.attr, | 1072 | &status.attr, |
@@ -1069,6 +1107,11 @@ static void __init intel_pstate_sysfs_expose_params(void) | |||
1069 | rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr); | 1107 | rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr); |
1070 | WARN_ON(rc); | 1108 | WARN_ON(rc); |
1071 | 1109 | ||
1110 | if (hwp_active) { | ||
1111 | rc = sysfs_create_file(intel_pstate_kobject, | ||
1112 | &hwp_dynamic_boost.attr); | ||
1113 | WARN_ON(rc); | ||
1114 | } | ||
1072 | } | 1115 | } |
1073 | /************************** sysfs end ************************/ | 1116 | /************************** sysfs end ************************/ |
1074 | 1117 | ||
@@ -1381,6 +1424,116 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
1381 | intel_pstate_set_min_pstate(cpu); | 1424 | intel_pstate_set_min_pstate(cpu); |
1382 | } | 1425 | } |
1383 | 1426 | ||
1427 | /* | ||
1428 | * Long hold time will keep high perf limits for long time, | ||
1429 | * which negatively impacts perf/watt for some workloads, | ||
1430 | * like specpower. 3ms is based on experiements on some | ||
1431 | * workoads. | ||
1432 | */ | ||
1433 | static int hwp_boost_hold_time_ns = 3 * NSEC_PER_MSEC; | ||
1434 | |||
1435 | static inline void intel_pstate_hwp_boost_up(struct cpudata *cpu) | ||
1436 | { | ||
1437 | u64 hwp_req = READ_ONCE(cpu->hwp_req_cached); | ||
1438 | u32 max_limit = (hwp_req & 0xff00) >> 8; | ||
1439 | u32 min_limit = (hwp_req & 0xff); | ||
1440 | u32 boost_level1; | ||
1441 | |||
1442 | /* | ||
1443 | * Cases to consider (User changes via sysfs or boot time): | ||
1444 | * If, P0 (Turbo max) = P1 (Guaranteed max) = min: | ||
1445 | * No boost, return. | ||
1446 | * If, P0 (Turbo max) > P1 (Guaranteed max) = min: | ||
1447 | * Should result in one level boost only for P0. | ||
1448 | * If, P0 (Turbo max) = P1 (Guaranteed max) > min: | ||
1449 | * Should result in two level boost: | ||
1450 | * (min + p1)/2 and P1. | ||
1451 | * If, P0 (Turbo max) > P1 (Guaranteed max) > min: | ||
1452 | * Should result in three level boost: | ||
1453 | * (min + p1)/2, P1 and P0. | ||
1454 | */ | ||
1455 | |||
1456 | /* If max and min are equal or already at max, nothing to boost */ | ||
1457 | if (max_limit == min_limit || cpu->hwp_boost_min >= max_limit) | ||
1458 | return; | ||
1459 | |||
1460 | if (!cpu->hwp_boost_min) | ||
1461 | cpu->hwp_boost_min = min_limit; | ||
1462 | |||
1463 | /* level at half way mark between min and guranteed */ | ||
1464 | boost_level1 = (HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) + min_limit) >> 1; | ||
1465 | |||
1466 | if (cpu->hwp_boost_min < boost_level1) | ||
1467 | cpu->hwp_boost_min = boost_level1; | ||
1468 | else if (cpu->hwp_boost_min < HWP_GUARANTEED_PERF(cpu->hwp_cap_cached)) | ||
1469 | cpu->hwp_boost_min = HWP_GUARANTEED_PERF(cpu->hwp_cap_cached); | ||
1470 | else if (cpu->hwp_boost_min == HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) && | ||
1471 | max_limit != HWP_GUARANTEED_PERF(cpu->hwp_cap_cached)) | ||
1472 | cpu->hwp_boost_min = max_limit; | ||
1473 | else | ||
1474 | return; | ||
1475 | |||
1476 | hwp_req = (hwp_req & ~GENMASK_ULL(7, 0)) | cpu->hwp_boost_min; | ||
1477 | wrmsrl(MSR_HWP_REQUEST, hwp_req); | ||
1478 | cpu->last_update = cpu->sample.time; | ||
1479 | } | ||
1480 | |||
1481 | static inline void intel_pstate_hwp_boost_down(struct cpudata *cpu) | ||
1482 | { | ||
1483 | if (cpu->hwp_boost_min) { | ||
1484 | bool expired; | ||
1485 | |||
1486 | /* Check if we are idle for hold time to boost down */ | ||
1487 | expired = time_after64(cpu->sample.time, cpu->last_update + | ||
1488 | hwp_boost_hold_time_ns); | ||
1489 | if (expired) { | ||
1490 | wrmsrl(MSR_HWP_REQUEST, cpu->hwp_req_cached); | ||
1491 | cpu->hwp_boost_min = 0; | ||
1492 | } | ||
1493 | } | ||
1494 | cpu->last_update = cpu->sample.time; | ||
1495 | } | ||
1496 | |||
1497 | static inline void intel_pstate_update_util_hwp_local(struct cpudata *cpu, | ||
1498 | u64 time) | ||
1499 | { | ||
1500 | cpu->sample.time = time; | ||
1501 | |||
1502 | if (cpu->sched_flags & SCHED_CPUFREQ_IOWAIT) { | ||
1503 | bool do_io = false; | ||
1504 | |||
1505 | cpu->sched_flags = 0; | ||
1506 | /* | ||
1507 | * Set iowait_boost flag and update time. Since IO WAIT flag | ||
1508 | * is set all the time, we can't just conclude that there is | ||
1509 | * some IO bound activity is scheduled on this CPU with just | ||
1510 | * one occurrence. If we receive at least two in two | ||
1511 | * consecutive ticks, then we treat as boost candidate. | ||
1512 | */ | ||
1513 | if (time_before64(time, cpu->last_io_update + 2 * TICK_NSEC)) | ||
1514 | do_io = true; | ||
1515 | |||
1516 | cpu->last_io_update = time; | ||
1517 | |||
1518 | if (do_io) | ||
1519 | intel_pstate_hwp_boost_up(cpu); | ||
1520 | |||
1521 | } else { | ||
1522 | intel_pstate_hwp_boost_down(cpu); | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | static inline void intel_pstate_update_util_hwp(struct update_util_data *data, | ||
1527 | u64 time, unsigned int flags) | ||
1528 | { | ||
1529 | struct cpudata *cpu = container_of(data, struct cpudata, update_util); | ||
1530 | |||
1531 | cpu->sched_flags |= flags; | ||
1532 | |||
1533 | if (smp_processor_id() == cpu->cpu) | ||
1534 | intel_pstate_update_util_hwp_local(cpu, time); | ||
1535 | } | ||
1536 | |||
1384 | static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu) | 1537 | static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu) |
1385 | { | 1538 | { |
1386 | struct sample *sample = &cpu->sample; | 1539 | struct sample *sample = &cpu->sample; |
@@ -1641,6 +1794,12 @@ static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = { | |||
1641 | {} | 1794 | {} |
1642 | }; | 1795 | }; |
1643 | 1796 | ||
1797 | static const struct x86_cpu_id intel_pstate_hwp_boost_ids[] = { | ||
1798 | ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), | ||
1799 | ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs), | ||
1800 | {} | ||
1801 | }; | ||
1802 | |||
1644 | static int intel_pstate_init_cpu(unsigned int cpunum) | 1803 | static int intel_pstate_init_cpu(unsigned int cpunum) |
1645 | { | 1804 | { |
1646 | struct cpudata *cpu; | 1805 | struct cpudata *cpu; |
@@ -1671,6 +1830,10 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||
1671 | intel_pstate_disable_ee(cpunum); | 1830 | intel_pstate_disable_ee(cpunum); |
1672 | 1831 | ||
1673 | intel_pstate_hwp_enable(cpu); | 1832 | intel_pstate_hwp_enable(cpu); |
1833 | |||
1834 | id = x86_match_cpu(intel_pstate_hwp_boost_ids); | ||
1835 | if (id) | ||
1836 | hwp_boost = true; | ||
1674 | } | 1837 | } |
1675 | 1838 | ||
1676 | intel_pstate_get_cpu_pstates(cpu); | 1839 | intel_pstate_get_cpu_pstates(cpu); |
@@ -1684,7 +1847,7 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num) | |||
1684 | { | 1847 | { |
1685 | struct cpudata *cpu = all_cpu_data[cpu_num]; | 1848 | struct cpudata *cpu = all_cpu_data[cpu_num]; |
1686 | 1849 | ||
1687 | if (hwp_active) | 1850 | if (hwp_active && !hwp_boost) |
1688 | return; | 1851 | return; |
1689 | 1852 | ||
1690 | if (cpu->update_util_set) | 1853 | if (cpu->update_util_set) |
@@ -1693,7 +1856,9 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num) | |||
1693 | /* Prevent intel_pstate_update_util() from using stale data. */ | 1856 | /* Prevent intel_pstate_update_util() from using stale data. */ |
1694 | cpu->sample.time = 0; | 1857 | cpu->sample.time = 0; |
1695 | cpufreq_add_update_util_hook(cpu_num, &cpu->update_util, | 1858 | cpufreq_add_update_util_hook(cpu_num, &cpu->update_util, |
1696 | intel_pstate_update_util); | 1859 | (hwp_active ? |
1860 | intel_pstate_update_util_hwp : | ||
1861 | intel_pstate_update_util)); | ||
1697 | cpu->update_util_set = true; | 1862 | cpu->update_util_set = true; |
1698 | } | 1863 | } |
1699 | 1864 | ||
@@ -1805,8 +1970,16 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
1805 | intel_pstate_set_update_util_hook(policy->cpu); | 1970 | intel_pstate_set_update_util_hook(policy->cpu); |
1806 | } | 1971 | } |
1807 | 1972 | ||
1808 | if (hwp_active) | 1973 | if (hwp_active) { |
1974 | /* | ||
1975 | * When hwp_boost was active before and dynamically it | ||
1976 | * was turned off, in that case we need to clear the | ||
1977 | * update util hook. | ||
1978 | */ | ||
1979 | if (!hwp_boost) | ||
1980 | intel_pstate_clear_update_util_hook(policy->cpu); | ||
1809 | intel_pstate_hwp_set(policy->cpu); | 1981 | intel_pstate_hwp_set(policy->cpu); |
1982 | } | ||
1810 | 1983 | ||
1811 | mutex_unlock(&intel_pstate_limits_lock); | 1984 | mutex_unlock(&intel_pstate_limits_lock); |
1812 | 1985 | ||
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 6ba709b6f095..3f0e2a14895a 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c | |||
@@ -217,7 +217,7 @@ static int ti_cpufreq_probe(struct platform_device *pdev) | |||
217 | if (!match) | 217 | if (!match) |
218 | return -ENODEV; | 218 | return -ENODEV; |
219 | 219 | ||
220 | opp_data = kzalloc(sizeof(*opp_data), GFP_KERNEL); | 220 | opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL); |
221 | if (!opp_data) | 221 | if (!opp_data) |
222 | return -ENOMEM; | 222 | return -ENOMEM; |
223 | 223 | ||
@@ -226,8 +226,7 @@ static int ti_cpufreq_probe(struct platform_device *pdev) | |||
226 | opp_data->cpu_dev = get_cpu_device(0); | 226 | opp_data->cpu_dev = get_cpu_device(0); |
227 | if (!opp_data->cpu_dev) { | 227 | if (!opp_data->cpu_dev) { |
228 | pr_err("%s: Failed to get device for CPU0\n", __func__); | 228 | pr_err("%s: Failed to get device for CPU0\n", __func__); |
229 | ret = ENODEV; | 229 | return -ENODEV; |
230 | goto free_opp_data; | ||
231 | } | 230 | } |
232 | 231 | ||
233 | opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); | 232 | opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); |
@@ -285,8 +284,6 @@ register_cpufreq_dt: | |||
285 | 284 | ||
286 | fail_put_node: | 285 | fail_put_node: |
287 | of_node_put(opp_data->opp_node); | 286 | of_node_put(opp_data->opp_node); |
288 | free_opp_data: | ||
289 | kfree(opp_data); | ||
290 | 287 | ||
291 | return ret; | 288 | return ret; |
292 | } | 289 | } |