aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-04-29 16:54:30 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-01 15:28:15 -0400
commitdd8683e97f12609fb3f8c4318628f0d246542f89 (patch)
tree9cd89a733706d7c6143125116f4a1c3cff9c4a6c /drivers/base
parenta5bef810ad9816a3a8e500d8832be77d52903a12 (diff)
PM / Domains: Rework default domain power off governor function, v2
The existing default domain power down governor function for PM domains, default_power_down_ok(), is supposed to check whether or not the PM QoS latency constraints of the devices in the domain will be violated if the domain is turned off by pm_genpd_poweroff(). However, the computations carried out by it don't reflect the definition of the PM QoS latency constrait in Documentation/ABI/testing/sysfs-devices-power. Make default_power_down_ok() follow the definition of the PM QoS latency constrait. In particular, make it only take latencies into account, because it doesn't matter how much time has elapsed since the domain's devices were suspended for the computation. Remove the break_even_ns and power_off_time fields from struct generic_pm_domain, because they are not necessary any more. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/domain.c2
-rw-r--r--drivers/base/power/domain_governor.c69
2 files changed, 35 insertions, 36 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 3c6e94fe058..d03a8c7ad84 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -381,6 +381,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
381 return 0; 381 return 0;
382 } 382 }
383 383
384 genpd->max_off_time_ns = -1;
384 if (genpd->gov && genpd->gov->power_down_ok) { 385 if (genpd->gov && genpd->gov->power_down_ok) {
385 if (!genpd->gov->power_down_ok(&genpd->domain)) 386 if (!genpd->gov->power_down_ok(&genpd->domain))
386 return -EAGAIN; 387 return -EAGAIN;
@@ -443,7 +444,6 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
443 } 444 }
444 445
445 genpd->status = GPD_STATE_POWER_OFF; 446 genpd->status = GPD_STATE_POWER_OFF;
446 genpd->power_off_time = ktime_get();
447 447
448 /* Update PM QoS information for devices in the domain. */ 448 /* Update PM QoS information for devices in the domain. */
449 list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) { 449 list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index a67f157a7a7..2aae623fd84 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -89,7 +89,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
89 struct pm_domain_data *pdd; 89 struct pm_domain_data *pdd;
90 s64 min_dev_off_time_ns; 90 s64 min_dev_off_time_ns;
91 s64 off_on_time_ns; 91 s64 off_on_time_ns;
92 ktime_t time_now = ktime_get();
93 92
94 off_on_time_ns = genpd->power_off_latency_ns + 93 off_on_time_ns = genpd->power_off_latency_ns +
95 genpd->power_on_latency_ns; 94 genpd->power_on_latency_ns;
@@ -118,8 +117,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
118 if (sd_max_off_ns < 0) 117 if (sd_max_off_ns < 0)
119 continue; 118 continue;
120 119
121 sd_max_off_ns -= ktime_to_ns(ktime_sub(time_now,
122 sd->power_off_time));
123 /* 120 /*
124 * Check if the subdomain is allowed to be off long enough for 121 * Check if the subdomain is allowed to be off long enough for
125 * the current domain to turn off and on (that's how much time 122 * the current domain to turn off and on (that's how much time
@@ -135,52 +132,54 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
135 min_dev_off_time_ns = -1; 132 min_dev_off_time_ns = -1;
136 list_for_each_entry(pdd, &genpd->dev_list, list_node) { 133 list_for_each_entry(pdd, &genpd->dev_list, list_node) {
137 struct gpd_timing_data *td; 134 struct gpd_timing_data *td;
138 struct device *dev = pdd->dev; 135 s64 constraint_ns;
139 s64 dev_off_time_ns;
140 136
141 if (!dev->driver || dev->power.max_time_suspended_ns < 0) 137 if (!pdd->dev->driver)
142 continue; 138 continue;
143 139
140 /*
141 * Check if the device is allowed to be off long enough for the
142 * domain to turn off and on (that's how much time it will
143 * have to wait worst case).
144 */
144 td = &to_gpd_data(pdd)->td; 145 td = &to_gpd_data(pdd)->td;
145 dev_off_time_ns = dev->power.max_time_suspended_ns - 146 constraint_ns = td->effective_constraint_ns;
146 (td->start_latency_ns + td->restore_state_latency_ns + 147 /* default_stop_ok() need not be called before us. */
147 ktime_to_ns(ktime_sub(time_now, 148 if (constraint_ns < 0) {
148 dev->power.suspend_time))); 149 constraint_ns = dev_pm_qos_read_value(pdd->dev);
149 if (dev_off_time_ns <= off_on_time_ns) 150 constraint_ns *= NSEC_PER_USEC;
150 return false; 151 }
151 152 if (constraint_ns == 0)
152 if (min_dev_off_time_ns > dev_off_time_ns 153 continue;
153 || min_dev_off_time_ns < 0)
154 min_dev_off_time_ns = dev_off_time_ns;
155 }
156 154
157 if (min_dev_off_time_ns < 0) {
158 /* 155 /*
159 * There are no latency constraints, so the domain can spend 156 * constraint_ns cannot be negative here, because the device has
160 * arbitrary time in the "off" state. 157 * been suspended.
161 */ 158 */
162 genpd->max_off_time_ns = -1; 159 constraint_ns -= td->restore_state_latency_ns;
163 return true; 160 if (constraint_ns <= off_on_time_ns)
161 return false;
162
163 if (min_dev_off_time_ns > constraint_ns
164 || min_dev_off_time_ns < 0)
165 min_dev_off_time_ns = constraint_ns;
164 } 166 }
165 167
166 /* 168 /*
167 * The difference between the computed minimum delta and the time needed 169 * If the computed minimum device off time is negative, there are no
168 * to turn the domain on is the maximum theoretical time this domain can 170 * latency constraints, so the domain can spend arbitrary time in the
169 * spend in the "off" state. 171 * "off" state.
170 */ 172 */
171 min_dev_off_time_ns -= genpd->power_on_latency_ns; 173 if (min_dev_off_time_ns < 0)
174 return true;
172 175
173 /* 176 /*
174 * If the difference between the computed minimum delta and the time 177 * The difference between the computed minimum device off time and the
175 * needed to turn the domain off and back on on is smaller than the 178 * time needed to turn the domain on is the maximum theoretical time
176 * domain's power break even time, removing power from the domain is not 179 * this domain can spend in the "off" state.
177 * worth it.
178 */ 180 */
179 if (genpd->break_even_ns > 181 genpd->max_off_time_ns = min_dev_off_time_ns -
180 min_dev_off_time_ns - genpd->power_off_latency_ns) 182 genpd->power_on_latency_ns;
181 return false;
182
183 genpd->max_off_time_ns = min_dev_off_time_ns;
184 return true; 183 return true;
185} 184}
186 185