diff options
Diffstat (limited to 'drivers/base/power/domain_governor.c')
-rw-r--r-- | drivers/base/power/domain_governor.c | 166 |
1 files changed, 125 insertions, 41 deletions
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 66a265bf5867..28dee3053f1f 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
@@ -14,6 +14,31 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_PM_RUNTIME | 15 | #ifdef CONFIG_PM_RUNTIME |
16 | 16 | ||
17 | static int dev_update_qos_constraint(struct device *dev, void *data) | ||
18 | { | ||
19 | s64 *constraint_ns_p = data; | ||
20 | s32 constraint_ns = -1; | ||
21 | |||
22 | if (dev->power.subsys_data && dev->power.subsys_data->domain_data) | ||
23 | constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; | ||
24 | |||
25 | if (constraint_ns < 0) { | ||
26 | constraint_ns = dev_pm_qos_read_value(dev); | ||
27 | constraint_ns *= NSEC_PER_USEC; | ||
28 | } | ||
29 | if (constraint_ns == 0) | ||
30 | return 0; | ||
31 | |||
32 | /* | ||
33 | * constraint_ns cannot be negative here, because the device has been | ||
34 | * suspended. | ||
35 | */ | ||
36 | if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) | ||
37 | *constraint_ns_p = constraint_ns; | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
17 | /** | 42 | /** |
18 | * default_stop_ok - Default PM domain governor routine for stopping devices. | 43 | * default_stop_ok - Default PM domain governor routine for stopping devices. |
19 | * @dev: Device to check. | 44 | * @dev: Device to check. |
@@ -21,14 +46,52 @@ | |||
21 | bool default_stop_ok(struct device *dev) | 46 | bool default_stop_ok(struct device *dev) |
22 | { | 47 | { |
23 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; | 48 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; |
49 | unsigned long flags; | ||
50 | s64 constraint_ns; | ||
24 | 51 | ||
25 | dev_dbg(dev, "%s()\n", __func__); | 52 | dev_dbg(dev, "%s()\n", __func__); |
26 | 53 | ||
27 | if (dev->power.max_time_suspended_ns < 0 || td->break_even_ns == 0) | 54 | spin_lock_irqsave(&dev->power.lock, flags); |
28 | return true; | 55 | |
56 | if (!td->constraint_changed) { | ||
57 | bool ret = td->cached_stop_ok; | ||
29 | 58 | ||
30 | return td->stop_latency_ns + td->start_latency_ns < td->break_even_ns | 59 | spin_unlock_irqrestore(&dev->power.lock, flags); |
31 | && td->break_even_ns < dev->power.max_time_suspended_ns; | 60 | return ret; |
61 | } | ||
62 | td->constraint_changed = false; | ||
63 | td->cached_stop_ok = false; | ||
64 | td->effective_constraint_ns = -1; | ||
65 | constraint_ns = __dev_pm_qos_read_value(dev); | ||
66 | |||
67 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
68 | |||
69 | if (constraint_ns < 0) | ||
70 | return false; | ||
71 | |||
72 | constraint_ns *= NSEC_PER_USEC; | ||
73 | /* | ||
74 | * We can walk the children without any additional locking, because | ||
75 | * they all have been suspended at this point and their | ||
76 | * effective_constraint_ns fields won't be modified in parallel with us. | ||
77 | */ | ||
78 | if (!dev->power.ignore_children) | ||
79 | device_for_each_child(dev, &constraint_ns, | ||
80 | dev_update_qos_constraint); | ||
81 | |||
82 | if (constraint_ns > 0) { | ||
83 | constraint_ns -= td->start_latency_ns; | ||
84 | if (constraint_ns == 0) | ||
85 | return false; | ||
86 | } | ||
87 | td->effective_constraint_ns = constraint_ns; | ||
88 | td->cached_stop_ok = constraint_ns > td->stop_latency_ns || | ||
89 | constraint_ns == 0; | ||
90 | /* | ||
91 | * The children have been suspended already, so we don't need to take | ||
92 | * their stop latencies into account here. | ||
93 | */ | ||
94 | return td->cached_stop_ok; | ||
32 | } | 95 | } |
33 | 96 | ||
34 | /** | 97 | /** |
@@ -42,9 +105,27 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
42 | struct generic_pm_domain *genpd = pd_to_genpd(pd); | 105 | struct generic_pm_domain *genpd = pd_to_genpd(pd); |
43 | struct gpd_link *link; | 106 | struct gpd_link *link; |
44 | struct pm_domain_data *pdd; | 107 | struct pm_domain_data *pdd; |
45 | s64 min_dev_off_time_ns; | 108 | s64 min_off_time_ns; |
46 | s64 off_on_time_ns; | 109 | s64 off_on_time_ns; |
47 | ktime_t time_now = ktime_get(); | 110 | |
111 | if (genpd->max_off_time_changed) { | ||
112 | struct gpd_link *link; | ||
113 | |||
114 | /* | ||
115 | * We have to invalidate the cached results for the masters, so | ||
116 | * use the observation that default_power_down_ok() is not | ||
117 | * going to be called for any master until this instance | ||
118 | * returns. | ||
119 | */ | ||
120 | list_for_each_entry(link, &genpd->slave_links, slave_node) | ||
121 | link->master->max_off_time_changed = true; | ||
122 | |||
123 | genpd->max_off_time_changed = false; | ||
124 | genpd->cached_power_down_ok = false; | ||
125 | genpd->max_off_time_ns = -1; | ||
126 | } else { | ||
127 | return genpd->cached_power_down_ok; | ||
128 | } | ||
48 | 129 | ||
49 | off_on_time_ns = genpd->power_off_latency_ns + | 130 | off_on_time_ns = genpd->power_off_latency_ns + |
50 | genpd->power_on_latency_ns; | 131 | genpd->power_on_latency_ns; |
@@ -61,6 +142,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
61 | to_gpd_data(pdd)->td.save_state_latency_ns; | 142 | to_gpd_data(pdd)->td.save_state_latency_ns; |
62 | } | 143 | } |
63 | 144 | ||
145 | min_off_time_ns = -1; | ||
64 | /* | 146 | /* |
65 | * Check if subdomains can be off for enough time. | 147 | * Check if subdomains can be off for enough time. |
66 | * | 148 | * |
@@ -73,8 +155,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
73 | if (sd_max_off_ns < 0) | 155 | if (sd_max_off_ns < 0) |
74 | continue; | 156 | continue; |
75 | 157 | ||
76 | sd_max_off_ns -= ktime_to_ns(ktime_sub(time_now, | ||
77 | sd->power_off_time)); | ||
78 | /* | 158 | /* |
79 | * Check if the subdomain is allowed to be off long enough for | 159 | * Check if the subdomain is allowed to be off long enough for |
80 | * the current domain to turn off and on (that's how much time | 160 | * the current domain to turn off and on (that's how much time |
@@ -82,60 +162,64 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
82 | */ | 162 | */ |
83 | if (sd_max_off_ns <= off_on_time_ns) | 163 | if (sd_max_off_ns <= off_on_time_ns) |
84 | return false; | 164 | return false; |
165 | |||
166 | if (min_off_time_ns > sd_max_off_ns || min_off_time_ns < 0) | ||
167 | min_off_time_ns = sd_max_off_ns; | ||
85 | } | 168 | } |
86 | 169 | ||
87 | /* | 170 | /* |
88 | * Check if the devices in the domain can be off enough time. | 171 | * Check if the devices in the domain can be off enough time. |
89 | */ | 172 | */ |
90 | min_dev_off_time_ns = -1; | ||
91 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { | 173 | list_for_each_entry(pdd, &genpd->dev_list, list_node) { |
92 | struct gpd_timing_data *td; | 174 | struct gpd_timing_data *td; |
93 | struct device *dev = pdd->dev; | 175 | s64 constraint_ns; |
94 | s64 dev_off_time_ns; | ||
95 | 176 | ||
96 | if (!dev->driver || dev->power.max_time_suspended_ns < 0) | 177 | if (!pdd->dev->driver) |
97 | continue; | 178 | continue; |
98 | 179 | ||
180 | /* | ||
181 | * Check if the device is allowed to be off long enough for the | ||
182 | * domain to turn off and on (that's how much time it will | ||
183 | * have to wait worst case). | ||
184 | */ | ||
99 | td = &to_gpd_data(pdd)->td; | 185 | td = &to_gpd_data(pdd)->td; |
100 | dev_off_time_ns = dev->power.max_time_suspended_ns - | 186 | constraint_ns = td->effective_constraint_ns; |
101 | (td->start_latency_ns + td->restore_state_latency_ns + | 187 | /* default_stop_ok() need not be called before us. */ |
102 | ktime_to_ns(ktime_sub(time_now, | 188 | if (constraint_ns < 0) { |
103 | dev->power.suspend_time))); | 189 | constraint_ns = dev_pm_qos_read_value(pdd->dev); |
104 | if (dev_off_time_ns <= off_on_time_ns) | 190 | constraint_ns *= NSEC_PER_USEC; |
105 | return false; | 191 | } |
106 | 192 | if (constraint_ns == 0) | |
107 | if (min_dev_off_time_ns > dev_off_time_ns | 193 | continue; |
108 | || min_dev_off_time_ns < 0) | ||
109 | min_dev_off_time_ns = dev_off_time_ns; | ||
110 | } | ||
111 | 194 | ||
112 | if (min_dev_off_time_ns < 0) { | ||
113 | /* | 195 | /* |
114 | * There are no latency constraints, so the domain can spend | 196 | * constraint_ns cannot be negative here, because the device has |
115 | * arbitrary time in the "off" state. | 197 | * been suspended. |
116 | */ | 198 | */ |
117 | genpd->max_off_time_ns = -1; | 199 | constraint_ns -= td->restore_state_latency_ns; |
118 | return true; | 200 | if (constraint_ns <= off_on_time_ns) |
201 | return false; | ||
202 | |||
203 | if (min_off_time_ns > constraint_ns || min_off_time_ns < 0) | ||
204 | min_off_time_ns = constraint_ns; | ||
119 | } | 205 | } |
120 | 206 | ||
207 | genpd->cached_power_down_ok = true; | ||
208 | |||
121 | /* | 209 | /* |
122 | * The difference between the computed minimum delta and the time needed | 210 | * If the computed minimum device off time is negative, there are no |
123 | * to turn the domain on is the maximum theoretical time this domain can | 211 | * latency constraints, so the domain can spend arbitrary time in the |
124 | * spend in the "off" state. | 212 | * "off" state. |
125 | */ | 213 | */ |
126 | min_dev_off_time_ns -= genpd->power_on_latency_ns; | 214 | if (min_off_time_ns < 0) |
215 | return true; | ||
127 | 216 | ||
128 | /* | 217 | /* |
129 | * If the difference between the computed minimum delta and the time | 218 | * The difference between the computed minimum subdomain or device off |
130 | * needed to turn the domain off and back on on is smaller than the | 219 | * time and the time needed to turn the domain on is the maximum |
131 | * domain's power break even time, removing power from the domain is not | 220 | * theoretical time this domain can spend in the "off" state. |
132 | * worth it. | ||
133 | */ | 221 | */ |
134 | if (genpd->break_even_ns > | 222 | genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns; |
135 | min_dev_off_time_ns - genpd->power_off_latency_ns) | ||
136 | return false; | ||
137 | |||
138 | genpd->max_off_time_ns = min_dev_off_time_ns; | ||
139 | return true; | 223 | return true; |
140 | } | 224 | } |
141 | 225 | ||