Skip to content

Commit 5937c3c

Browse files
storulfrafaeljw
authored andcommitted
PM: domains: Drop/restore performance state votes for devices at runtime PM
A subsystem/driver that need to manage OPPs for its device, should typically drop its vote for the OPP when the device becomes runtime suspended. In this way, the corresponding aggregation of the performance state votes that is managed in genpd for the attached PM domain, may find that the aggregated vote can be decreased. Hence, it may allow genpd to set the lower performance state for the PM domain, thus avoiding to waste energy. To accomplish this, typically a subsystem/driver would need to call dev_pm_opp_set_rate|opp() for its device from its ->runtime_suspend() callback, to drop the vote for the OPP. Accordingly, it needs another call to dev_pm_opp_set_rate|opp() to restore the vote for the OPP from its ->runtime_resume() callback. To avoid boilerplate code in subsystems/driver to deal with these things, let's instead manage this internally in genpd. Signed-off-by: Ulf Hansson <[email protected]> Tested-by: Dmitry Osipenko <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent d97fe10 commit 5937c3c

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

drivers/base/power/domain.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,23 @@ static int genpd_set_performance_state(struct device *dev, unsigned int state)
400400
return ret;
401401
}
402402

403+
static int genpd_drop_performance_state(struct device *dev)
404+
{
405+
unsigned int prev_state = dev_gpd_data(dev)->performance_state;
406+
407+
if (!genpd_set_performance_state(dev, 0))
408+
return prev_state;
409+
410+
return 0;
411+
}
412+
413+
static void genpd_restore_performance_state(struct device *dev,
414+
unsigned int state)
415+
{
416+
if (state)
417+
genpd_set_performance_state(dev, state);
418+
}
419+
403420
/**
404421
* dev_pm_genpd_set_performance_state- Set performance state of device's power
405422
* domain.
@@ -843,7 +860,8 @@ static int genpd_runtime_suspend(struct device *dev)
843860
{
844861
struct generic_pm_domain *genpd;
845862
bool (*suspend_ok)(struct device *__dev);
846-
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
863+
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
864+
struct gpd_timing_data *td = &gpd_data->td;
847865
bool runtime_pm = pm_runtime_enabled(dev);
848866
ktime_t time_start;
849867
s64 elapsed_ns;
@@ -900,6 +918,7 @@ static int genpd_runtime_suspend(struct device *dev)
900918
return 0;
901919

902920
genpd_lock(genpd);
921+
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
903922
genpd_power_off(genpd, true, 0);
904923
genpd_unlock(genpd);
905924

@@ -917,7 +936,8 @@ static int genpd_runtime_suspend(struct device *dev)
917936
static int genpd_runtime_resume(struct device *dev)
918937
{
919938
struct generic_pm_domain *genpd;
920-
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
939+
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
940+
struct gpd_timing_data *td = &gpd_data->td;
921941
bool runtime_pm = pm_runtime_enabled(dev);
922942
ktime_t time_start;
923943
s64 elapsed_ns;
@@ -941,6 +961,8 @@ static int genpd_runtime_resume(struct device *dev)
941961

942962
genpd_lock(genpd);
943963
ret = genpd_power_on(genpd, 0);
964+
if (!ret)
965+
genpd_restore_performance_state(dev, gpd_data->rpm_pstate);
944966
genpd_unlock(genpd);
945967

946968
if (ret)
@@ -979,6 +1001,7 @@ static int genpd_runtime_resume(struct device *dev)
9791001
err_poweroff:
9801002
if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) {
9811003
genpd_lock(genpd);
1004+
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
9821005
genpd_power_off(genpd, true, 0);
9831006
genpd_unlock(genpd);
9841007
}

include/linux/pm_domain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ struct generic_pm_domain_data {
198198
struct notifier_block *power_nb;
199199
int cpu;
200200
unsigned int performance_state;
201+
unsigned int rpm_pstate;
201202
ktime_t next_wakeup;
202203
void *data;
203204
};

0 commit comments

Comments
 (0)