mirror of
https://github.com/ukui/kernel.git
synced 2026-03-09 10:07:04 -07:00
Merge branch 'pm-domains'
Merge generlic power domains update for 5.19-rc1: - Extend dev_pm_domain_detach() doc (Krzysztof Kozlowski). - Move genpd's time-accounting to ktime_get_mono_fast_ns() (Ulf Hansson). - Improve the way genpd deals with its governors (Ulf Hansson). * pm-domains: PM: domains: Trust domain-idle-states from DT to be correct by genpd PM: domains: Measure power-on/off latencies in genpd based on a governor PM: domains: Allocate governor data dynamically based on a genpd governor PM: domains: Clean up some code in pm_genpd_init() and genpd_remove() PM: domains: Fix initialization of genpd's next_wakeup PM: domains: Fixup QoS latency measurements for IRQ safe devices in genpd PM: domains: Measure suspend/resume latencies in genpd based on governor PM: domains: Move the next_wakeup variable into the struct gpd_timing_data PM: domains: Allocate gpd_timing_data dynamically based on governor PM: domains: Skip another warning in irq_safe_dev_in_sleep_domain() PM: domains: Rename irq_safe_dev_in_no_sleep_domain() in genpd PM: domains: Don't check PM_QOS_FLAG_NO_POWER_OFF in genpd PM: domains: Drop redundant code for genpd always-on governor PM: domains: Add GENPD_FLAG_RPM_ALWAYS_ON for the always-on governor PM: domains: Move genpd's time-accounting to ktime_get_mono_fast_ns() PM: domains: Extend dev_pm_domain_detach() doc
This commit is contained in:
@@ -172,10 +172,10 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
|
||||
* @dev: Device to detach.
|
||||
* @power_off: Used to indicate whether we should power off the device.
|
||||
*
|
||||
* This functions will reverse the actions from dev_pm_domain_attach() and
|
||||
* dev_pm_domain_attach_by_id(), thus it detaches @dev from its PM domain.
|
||||
* Typically it should be invoked during the remove phase, either from
|
||||
* subsystem level code or from drivers.
|
||||
* This functions will reverse the actions from dev_pm_domain_attach(),
|
||||
* dev_pm_domain_attach_by_id() and dev_pm_domain_attach_by_name(), thus it
|
||||
* detaches @dev from its PM domain. Typically it should be invoked during the
|
||||
* remove phase, either from subsystem level code or from drivers.
|
||||
*
|
||||
* Callers must ensure proper synchronization of this function with power
|
||||
* management callbacks.
|
||||
|
||||
+170
-108
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,8 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
|
||||
s64 constraint_ns;
|
||||
|
||||
if (dev->power.subsys_data && dev->power.subsys_data->domain_data) {
|
||||
struct gpd_timing_data *td = dev_gpd_data(dev)->td;
|
||||
|
||||
/*
|
||||
* Only take suspend-time QoS constraints of devices into
|
||||
* account, because constraints updated after the device has
|
||||
@@ -25,7 +27,8 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
|
||||
* anyway. In order for them to take effect, the device has to
|
||||
* be resumed and suspended again.
|
||||
*/
|
||||
constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns;
|
||||
constraint_ns = td ? td->effective_constraint_ns :
|
||||
PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS;
|
||||
} else {
|
||||
/*
|
||||
* The child is not in a domain and there's no info on its
|
||||
@@ -49,7 +52,7 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
|
||||
*/
|
||||
static bool default_suspend_ok(struct device *dev)
|
||||
{
|
||||
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
|
||||
struct gpd_timing_data *td = dev_gpd_data(dev)->td;
|
||||
unsigned long flags;
|
||||
s64 constraint_ns;
|
||||
|
||||
@@ -136,26 +139,28 @@ static void update_domain_next_wakeup(struct generic_pm_domain *genpd, ktime_t n
|
||||
* is able to enter its optimal idle state.
|
||||
*/
|
||||
list_for_each_entry(pdd, &genpd->dev_list, list_node) {
|
||||
next_wakeup = to_gpd_data(pdd)->next_wakeup;
|
||||
next_wakeup = to_gpd_data(pdd)->td->next_wakeup;
|
||||
if (next_wakeup != KTIME_MAX && !ktime_before(next_wakeup, now))
|
||||
if (ktime_before(next_wakeup, domain_wakeup))
|
||||
domain_wakeup = next_wakeup;
|
||||
}
|
||||
|
||||
list_for_each_entry(link, &genpd->parent_links, parent_node) {
|
||||
next_wakeup = link->child->next_wakeup;
|
||||
struct genpd_governor_data *cgd = link->child->gd;
|
||||
|
||||
next_wakeup = cgd ? cgd->next_wakeup : KTIME_MAX;
|
||||
if (next_wakeup != KTIME_MAX && !ktime_before(next_wakeup, now))
|
||||
if (ktime_before(next_wakeup, domain_wakeup))
|
||||
domain_wakeup = next_wakeup;
|
||||
}
|
||||
|
||||
genpd->next_wakeup = domain_wakeup;
|
||||
genpd->gd->next_wakeup = domain_wakeup;
|
||||
}
|
||||
|
||||
static bool next_wakeup_allows_state(struct generic_pm_domain *genpd,
|
||||
unsigned int state, ktime_t now)
|
||||
{
|
||||
ktime_t domain_wakeup = genpd->next_wakeup;
|
||||
ktime_t domain_wakeup = genpd->gd->next_wakeup;
|
||||
s64 idle_time_ns, min_sleep_ns;
|
||||
|
||||
min_sleep_ns = genpd->states[state].power_off_latency_ns +
|
||||
@@ -185,8 +190,9 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
|
||||
* All subdomains have been powered off already at this point.
|
||||
*/
|
||||
list_for_each_entry(link, &genpd->parent_links, parent_node) {
|
||||
struct generic_pm_domain *sd = link->child;
|
||||
s64 sd_max_off_ns = sd->max_off_time_ns;
|
||||
struct genpd_governor_data *cgd = link->child->gd;
|
||||
|
||||
s64 sd_max_off_ns = cgd ? cgd->max_off_time_ns : -1;
|
||||
|
||||
if (sd_max_off_ns < 0)
|
||||
continue;
|
||||
@@ -215,7 +221,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
|
||||
* domain to turn off and on (that's how much time it will
|
||||
* have to wait worst case).
|
||||
*/
|
||||
td = &to_gpd_data(pdd)->td;
|
||||
td = to_gpd_data(pdd)->td;
|
||||
constraint_ns = td->effective_constraint_ns;
|
||||
/*
|
||||
* Zero means "no suspend at all" and this runs only when all
|
||||
@@ -244,7 +250,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
|
||||
* time and the time needed to turn the domain on is the maximum
|
||||
* theoretical time this domain can spend in the "off" state.
|
||||
*/
|
||||
genpd->max_off_time_ns = min_off_time_ns -
|
||||
genpd->gd->max_off_time_ns = min_off_time_ns -
|
||||
genpd->states[state].power_on_latency_ns;
|
||||
return true;
|
||||
}
|
||||
@@ -259,6 +265,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
|
||||
static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
{
|
||||
struct generic_pm_domain *genpd = pd_to_genpd(pd);
|
||||
struct genpd_governor_data *gd = genpd->gd;
|
||||
int state_idx = genpd->state_count - 1;
|
||||
struct gpd_link *link;
|
||||
|
||||
@@ -269,11 +276,11 @@ static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
* cannot be met.
|
||||
*/
|
||||
update_domain_next_wakeup(genpd, now);
|
||||
if ((genpd->flags & GENPD_FLAG_MIN_RESIDENCY) && (genpd->next_wakeup != KTIME_MAX)) {
|
||||
if ((genpd->flags & GENPD_FLAG_MIN_RESIDENCY) && (gd->next_wakeup != KTIME_MAX)) {
|
||||
/* Let's find out the deepest domain idle state, the devices prefer */
|
||||
while (state_idx >= 0) {
|
||||
if (next_wakeup_allows_state(genpd, state_idx, now)) {
|
||||
genpd->max_off_time_changed = true;
|
||||
gd->max_off_time_changed = true;
|
||||
break;
|
||||
}
|
||||
state_idx--;
|
||||
@@ -281,14 +288,14 @@ static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
|
||||
if (state_idx < 0) {
|
||||
state_idx = 0;
|
||||
genpd->cached_power_down_ok = false;
|
||||
gd->cached_power_down_ok = false;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!genpd->max_off_time_changed) {
|
||||
genpd->state_idx = genpd->cached_power_down_state_idx;
|
||||
return genpd->cached_power_down_ok;
|
||||
if (!gd->max_off_time_changed) {
|
||||
genpd->state_idx = gd->cached_power_down_state_idx;
|
||||
return gd->cached_power_down_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -297,12 +304,16 @@ static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
* going to be called for any parent until this instance
|
||||
* returns.
|
||||
*/
|
||||
list_for_each_entry(link, &genpd->child_links, child_node)
|
||||
link->parent->max_off_time_changed = true;
|
||||
list_for_each_entry(link, &genpd->child_links, child_node) {
|
||||
struct genpd_governor_data *pgd = link->parent->gd;
|
||||
|
||||
genpd->max_off_time_ns = -1;
|
||||
genpd->max_off_time_changed = false;
|
||||
genpd->cached_power_down_ok = true;
|
||||
if (pgd)
|
||||
pgd->max_off_time_changed = true;
|
||||
}
|
||||
|
||||
gd->max_off_time_ns = -1;
|
||||
gd->max_off_time_changed = false;
|
||||
gd->cached_power_down_ok = true;
|
||||
|
||||
/*
|
||||
* Find a state to power down to, starting from the state
|
||||
@@ -310,7 +321,7 @@ static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
*/
|
||||
while (!__default_power_down_ok(pd, state_idx)) {
|
||||
if (state_idx == 0) {
|
||||
genpd->cached_power_down_ok = false;
|
||||
gd->cached_power_down_ok = false;
|
||||
break;
|
||||
}
|
||||
state_idx--;
|
||||
@@ -318,8 +329,8 @@ static bool _default_power_down_ok(struct dev_pm_domain *pd, ktime_t now)
|
||||
|
||||
done:
|
||||
genpd->state_idx = state_idx;
|
||||
genpd->cached_power_down_state_idx = genpd->state_idx;
|
||||
return genpd->cached_power_down_ok;
|
||||
gd->cached_power_down_state_idx = genpd->state_idx;
|
||||
return gd->cached_power_down_ok;
|
||||
}
|
||||
|
||||
static bool default_power_down_ok(struct dev_pm_domain *pd)
|
||||
@@ -327,11 +338,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
|
||||
return _default_power_down_ok(pd, ktime_get());
|
||||
}
|
||||
|
||||
static bool always_on_power_down_ok(struct dev_pm_domain *domain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
static bool cpu_power_down_ok(struct dev_pm_domain *pd)
|
||||
{
|
||||
@@ -401,6 +407,5 @@ struct dev_power_governor simple_qos_governor = {
|
||||
* pm_genpd_gov_always_on - A governor implementing an always-on policy
|
||||
*/
|
||||
struct dev_power_governor pm_domain_always_on_gov = {
|
||||
.power_down_ok = always_on_power_down_ok,
|
||||
.suspend_ok = default_suspend_ok,
|
||||
};
|
||||
|
||||
+14
-10
@@ -91,6 +91,14 @@ struct gpd_dev_ops {
|
||||
int (*stop)(struct device *dev);
|
||||
};
|
||||
|
||||
struct genpd_governor_data {
|
||||
s64 max_off_time_ns;
|
||||
bool max_off_time_changed;
|
||||
ktime_t next_wakeup;
|
||||
bool cached_power_down_ok;
|
||||
bool cached_power_down_state_idx;
|
||||
};
|
||||
|
||||
struct genpd_power_state {
|
||||
s64 power_off_latency_ns;
|
||||
s64 power_on_latency_ns;
|
||||
@@ -98,7 +106,7 @@ struct genpd_power_state {
|
||||
u64 usage;
|
||||
u64 rejected;
|
||||
struct fwnode_handle *fwnode;
|
||||
ktime_t idle_time;
|
||||
u64 idle_time;
|
||||
void *data;
|
||||
};
|
||||
|
||||
@@ -114,6 +122,7 @@ struct generic_pm_domain {
|
||||
struct list_head child_links; /* Links with PM domain as a child */
|
||||
struct list_head dev_list; /* List of devices */
|
||||
struct dev_power_governor *gov;
|
||||
struct genpd_governor_data *gd; /* Data used by a genpd governor. */
|
||||
struct work_struct power_off_work;
|
||||
struct fwnode_handle *provider; /* Identity of the domain provider */
|
||||
bool has_provider;
|
||||
@@ -134,11 +143,6 @@ struct generic_pm_domain {
|
||||
int (*set_performance_state)(struct generic_pm_domain *genpd,
|
||||
unsigned int state);
|
||||
struct gpd_dev_ops dev_ops;
|
||||
s64 max_off_time_ns; /* Maximum allowed "suspended" time. */
|
||||
ktime_t next_wakeup; /* Maintained by the domain governor */
|
||||
bool max_off_time_changed;
|
||||
bool cached_power_down_ok;
|
||||
bool cached_power_down_state_idx;
|
||||
int (*attach_dev)(struct generic_pm_domain *domain,
|
||||
struct device *dev);
|
||||
void (*detach_dev)(struct generic_pm_domain *domain,
|
||||
@@ -149,8 +153,8 @@ struct generic_pm_domain {
|
||||
unsigned int state_count);
|
||||
unsigned int state_count; /* number of states */
|
||||
unsigned int state_idx; /* state that genpd will go to when off */
|
||||
ktime_t on_time;
|
||||
ktime_t accounting_time;
|
||||
u64 on_time;
|
||||
u64 accounting_time;
|
||||
const struct genpd_lock_ops *lock_ops;
|
||||
union {
|
||||
struct mutex mlock;
|
||||
@@ -182,6 +186,7 @@ struct gpd_timing_data {
|
||||
s64 suspend_latency_ns;
|
||||
s64 resume_latency_ns;
|
||||
s64 effective_constraint_ns;
|
||||
ktime_t next_wakeup;
|
||||
bool constraint_changed;
|
||||
bool cached_suspend_ok;
|
||||
};
|
||||
@@ -193,14 +198,13 @@ struct pm_domain_data {
|
||||
|
||||
struct generic_pm_domain_data {
|
||||
struct pm_domain_data base;
|
||||
struct gpd_timing_data td;
|
||||
struct gpd_timing_data *td;
|
||||
struct notifier_block nb;
|
||||
struct notifier_block *power_nb;
|
||||
int cpu;
|
||||
unsigned int performance_state;
|
||||
unsigned int default_pstate;
|
||||
unsigned int rpm_pstate;
|
||||
ktime_t next_wakeup;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user