Skip to content

Commit dcc0b6f

Browse files
committed
Merge branches 'pm-opp' and 'pm-cpufreq'
Merge operating performance points (OPP) framework updates for and intel_pstate driver fixes for 5.16-rc1. * pm-opp: dt-bindings: opp: Allow multi-worded OPP entry name opp: Fix return in _opp_add_static_v2() PM / devfreq: tegra30: Check whether clk_round_rate() returns zero rate PM / devfreq: tegra30: Use resource-managed helpers PM / devfreq: Add devm_devfreq_add_governor() opp: Add more resource-managed variants of dev_pm_opp_of_add_table() opp: Change type of dev_pm_opp_attach_genpd(names) argument opp: Fix required-opps phandle array count check * pm-cpufreq: cpufreq: intel_pstate: Clear HWP Status during HWP Interrupt enable cpufreq: intel_pstate: Fix unchecked MSR 0x773 access cpufreq: intel_pstate: Clear HWP desired on suspend/shutdown and offline
3 parents 2aa3660 + 5c83017 + 074d0cd commit dcc0b6f

File tree

8 files changed

+171
-81
lines changed

8 files changed

+171
-81
lines changed

Documentation/devicetree/bindings/opp/opp-v2-base.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ properties:
3333
type: boolean
3434

3535
patternProperties:
36-
'^opp-?[0-9]+$':
36+
'^opp(-?[0-9]+)*$':
3737
type: object
3838
description:
3939
One or more OPP nodes describing voltage-current-frequency combinations.

drivers/cpufreq/intel_pstate.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,9 +1006,16 @@ static void intel_pstate_hwp_offline(struct cpudata *cpu)
10061006
*/
10071007
value &= ~GENMASK_ULL(31, 24);
10081008
value |= HWP_ENERGY_PERF_PREFERENCE(cpu->epp_cached);
1009-
WRITE_ONCE(cpu->hwp_req_cached, value);
10101009
}
10111010

1011+
/*
1012+
* Clear the desired perf field in the cached HWP request value to
1013+
* prevent nonzero desired values from being leaked into the active
1014+
* mode.
1015+
*/
1016+
value &= ~HWP_DESIRED_PERF(~0L);
1017+
WRITE_ONCE(cpu->hwp_req_cached, value);
1018+
10121019
value &= ~GENMASK_ULL(31, 0);
10131020
min_perf = HWP_LOWEST_PERF(READ_ONCE(cpu->hwp_cap_cached));
10141021

@@ -1620,6 +1627,9 @@ static void intel_pstate_disable_hwp_interrupt(struct cpudata *cpudata)
16201627
{
16211628
unsigned long flags;
16221629

1630+
if (!boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
1631+
return;
1632+
16231633
/* wrmsrl_on_cpu has to be outside spinlock as this can result in IPC */
16241634
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
16251635

@@ -1642,6 +1652,7 @@ static void intel_pstate_enable_hwp_interrupt(struct cpudata *cpudata)
16421652

16431653
/* wrmsrl_on_cpu has to be outside spinlock as this can result in IPC */
16441654
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x01);
1655+
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_STATUS, 0);
16451656
}
16461657
}
16471658

@@ -3003,6 +3014,27 @@ static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy)
30033014
return intel_pstate_cpu_exit(policy);
30043015
}
30053016

3017+
static int intel_cpufreq_suspend(struct cpufreq_policy *policy)
3018+
{
3019+
intel_pstate_suspend(policy);
3020+
3021+
if (hwp_active) {
3022+
struct cpudata *cpu = all_cpu_data[policy->cpu];
3023+
u64 value = READ_ONCE(cpu->hwp_req_cached);
3024+
3025+
/*
3026+
* Clear the desired perf field in MSR_HWP_REQUEST in case
3027+
* intel_cpufreq_adjust_perf() is in use and the last value
3028+
* written by it may not be suitable.
3029+
*/
3030+
value &= ~HWP_DESIRED_PERF(~0L);
3031+
wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value);
3032+
WRITE_ONCE(cpu->hwp_req_cached, value);
3033+
}
3034+
3035+
return 0;
3036+
}
3037+
30063038
static struct cpufreq_driver intel_cpufreq = {
30073039
.flags = CPUFREQ_CONST_LOOPS,
30083040
.verify = intel_cpufreq_verify_policy,
@@ -3012,7 +3044,7 @@ static struct cpufreq_driver intel_cpufreq = {
30123044
.exit = intel_cpufreq_cpu_exit,
30133045
.offline = intel_cpufreq_cpu_offline,
30143046
.online = intel_pstate_cpu_online,
3015-
.suspend = intel_pstate_suspend,
3047+
.suspend = intel_cpufreq_suspend,
30163048
.resume = intel_pstate_resume,
30173049
.update_limits = intel_pstate_update_limits,
30183050
.name = "intel_cpufreq",

drivers/devfreq/devfreq.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,32 @@ int devfreq_add_governor(struct devfreq_governor *governor)
13011301
}
13021302
EXPORT_SYMBOL(devfreq_add_governor);
13031303

1304+
static void devm_devfreq_remove_governor(void *governor)
1305+
{
1306+
WARN_ON(devfreq_remove_governor(governor));
1307+
}
1308+
1309+
/**
1310+
* devm_devfreq_add_governor() - Add devfreq governor
1311+
* @dev: device which adds devfreq governor
1312+
* @governor: the devfreq governor to be added
1313+
*
1314+
* This is a resource-managed variant of devfreq_add_governor().
1315+
*/
1316+
int devm_devfreq_add_governor(struct device *dev,
1317+
struct devfreq_governor *governor)
1318+
{
1319+
int err;
1320+
1321+
err = devfreq_add_governor(governor);
1322+
if (err)
1323+
return err;
1324+
1325+
return devm_add_action_or_reset(dev, devm_devfreq_remove_governor,
1326+
governor);
1327+
}
1328+
EXPORT_SYMBOL(devm_devfreq_add_governor);
1329+
13041330
/**
13051331
* devfreq_remove_governor() - Remove devfreq feature from a device.
13061332
* @governor: the devfreq governor to be removed

drivers/devfreq/governor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay);
8484
int devfreq_add_governor(struct devfreq_governor *governor);
8585
int devfreq_remove_governor(struct devfreq_governor *governor);
8686

87+
int devm_devfreq_add_governor(struct device *dev,
88+
struct devfreq_governor *governor);
89+
8790
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
8891
int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
8992

drivers/devfreq/tegra30-devfreq.c

Lines changed: 47 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ struct tegra_devfreq_soc_data {
178178

179179
struct tegra_devfreq {
180180
struct devfreq *devfreq;
181-
struct opp_table *opp_table;
182181

183182
struct reset_control *reset;
184183
struct clk *clock;
@@ -789,6 +788,39 @@ static struct devfreq_governor tegra_devfreq_governor = {
789788
.event_handler = tegra_governor_event_handler,
790789
};
791790

791+
static void devm_tegra_devfreq_deinit_hw(void *data)
792+
{
793+
struct tegra_devfreq *tegra = data;
794+
795+
reset_control_reset(tegra->reset);
796+
clk_disable_unprepare(tegra->clock);
797+
}
798+
799+
static int devm_tegra_devfreq_init_hw(struct device *dev,
800+
struct tegra_devfreq *tegra)
801+
{
802+
int err;
803+
804+
err = clk_prepare_enable(tegra->clock);
805+
if (err) {
806+
dev_err(dev, "Failed to prepare and enable ACTMON clock\n");
807+
return err;
808+
}
809+
810+
err = devm_add_action_or_reset(dev, devm_tegra_devfreq_deinit_hw,
811+
tegra);
812+
if (err)
813+
return err;
814+
815+
err = reset_control_reset(tegra->reset);
816+
if (err) {
817+
dev_err(dev, "Failed to reset hardware: %d\n", err);
818+
return err;
819+
}
820+
821+
return err;
822+
}
823+
792824
static int tegra_devfreq_probe(struct platform_device *pdev)
793825
{
794826
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
@@ -842,38 +874,26 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
842874
return err;
843875
}
844876

845-
tegra->opp_table = dev_pm_opp_set_supported_hw(&pdev->dev,
846-
&hw_version, 1);
847-
err = PTR_ERR_OR_ZERO(tegra->opp_table);
877+
err = devm_pm_opp_set_supported_hw(&pdev->dev, &hw_version, 1);
848878
if (err) {
849879
dev_err(&pdev->dev, "Failed to set supported HW: %d\n", err);
850880
return err;
851881
}
852882

853-
err = dev_pm_opp_of_add_table_noclk(&pdev->dev, 0);
883+
err = devm_pm_opp_of_add_table_noclk(&pdev->dev, 0);
854884
if (err) {
855885
dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err);
856-
goto put_hw;
857-
}
858-
859-
err = clk_prepare_enable(tegra->clock);
860-
if (err) {
861-
dev_err(&pdev->dev,
862-
"Failed to prepare and enable ACTMON clock\n");
863-
goto remove_table;
886+
return err;
864887
}
865888

866-
err = reset_control_reset(tegra->reset);
867-
if (err) {
868-
dev_err(&pdev->dev, "Failed to reset hardware: %d\n", err);
869-
goto disable_clk;
870-
}
889+
err = devm_tegra_devfreq_init_hw(&pdev->dev, tegra);
890+
if (err)
891+
return err;
871892

872893
rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
873-
if (rate < 0) {
894+
if (rate <= 0) {
874895
dev_err(&pdev->dev, "Failed to round clock rate: %ld\n", rate);
875-
err = rate;
876-
goto disable_clk;
896+
return rate ?: -EINVAL;
877897
}
878898

879899
tegra->max_freq = rate / KHZ;
@@ -892,52 +912,18 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
892912
INIT_DELAYED_WORK(&tegra->cpufreq_update_work,
893913
tegra_actmon_delayed_update);
894914

895-
err = devfreq_add_governor(&tegra_devfreq_governor);
915+
err = devm_devfreq_add_governor(&pdev->dev, &tegra_devfreq_governor);
896916
if (err) {
897917
dev_err(&pdev->dev, "Failed to add governor: %d\n", err);
898-
goto remove_opps;
918+
return err;
899919
}
900920

901921
tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
902922

903-
devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile,
904-
"tegra_actmon", NULL);
905-
if (IS_ERR(devfreq)) {
906-
err = PTR_ERR(devfreq);
907-
goto remove_governor;
908-
}
909-
910-
return 0;
911-
912-
remove_governor:
913-
devfreq_remove_governor(&tegra_devfreq_governor);
914-
915-
remove_opps:
916-
dev_pm_opp_remove_all_dynamic(&pdev->dev);
917-
918-
reset_control_reset(tegra->reset);
919-
disable_clk:
920-
clk_disable_unprepare(tegra->clock);
921-
remove_table:
922-
dev_pm_opp_of_remove_table(&pdev->dev);
923-
put_hw:
924-
dev_pm_opp_put_supported_hw(tegra->opp_table);
925-
926-
return err;
927-
}
928-
929-
static int tegra_devfreq_remove(struct platform_device *pdev)
930-
{
931-
struct tegra_devfreq *tegra = platform_get_drvdata(pdev);
932-
933-
devfreq_remove_device(tegra->devfreq);
934-
devfreq_remove_governor(&tegra_devfreq_governor);
935-
936-
reset_control_reset(tegra->reset);
937-
clk_disable_unprepare(tegra->clock);
938-
939-
dev_pm_opp_of_remove_table(&pdev->dev);
940-
dev_pm_opp_put_supported_hw(tegra->opp_table);
923+
devfreq = devm_devfreq_add_device(&pdev->dev, &tegra_devfreq_profile,
924+
"tegra_actmon", NULL);
925+
if (IS_ERR(devfreq))
926+
return PTR_ERR(devfreq);
941927

942928
return 0;
943929
}
@@ -967,7 +953,6 @@ MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match);
967953

968954
static struct platform_driver tegra_devfreq_driver = {
969955
.probe = tegra_devfreq_probe,
970-
.remove = tegra_devfreq_remove,
971956
.driver = {
972957
.name = "tegra-devfreq",
973958
.of_match_table = tegra_devfreq_of_match,

drivers/opp/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,12 +2348,12 @@ static void _opp_detach_genpd(struct opp_table *opp_table)
23482348
* "required-opps" are added in DT.
23492349
*/
23502350
struct opp_table *dev_pm_opp_attach_genpd(struct device *dev,
2351-
const char **names, struct device ***virt_devs)
2351+
const char * const *names, struct device ***virt_devs)
23522352
{
23532353
struct opp_table *opp_table;
23542354
struct device *virt_dev;
23552355
int index = 0, ret = -EINVAL;
2356-
const char **name = names;
2356+
const char * const *name = names;
23572357

23582358
opp_table = _add_opp_table(dev, false);
23592359
if (IS_ERR(opp_table))
@@ -2457,7 +2457,7 @@ static void devm_pm_opp_detach_genpd(void *data)
24572457
*
24582458
* Return: 0 on success and errorno otherwise.
24592459
*/
2460-
int devm_pm_opp_attach_genpd(struct device *dev, const char **names,
2460+
int devm_pm_opp_attach_genpd(struct device *dev, const char * const *names,
24612461
struct device ***virt_devs)
24622462
{
24632463
struct opp_table *opp_table;

0 commit comments

Comments
 (0)