diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/device_pm.c | 4 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 25 | ||||
-rw-r--r-- | drivers/opp/core.c | 17 | ||||
-rw-r--r-- | drivers/opp/of.c | 30 |
4 files changed, 38 insertions, 38 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 3f8958007a93..08bb9f2f2d23 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -166,6 +166,10 @@ int acpi_device_set_power(struct acpi_device *device, int state) || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) return -EINVAL; + acpi_handle_debug(device->handle, "Power state change: %s -> %s\n", + acpi_power_state_string(device->power.state), + acpi_power_state_string(state)); + /* Make sure this is a valid target state */ /* There is a special case for D0 addressed below. */ diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b063bc41b0a9..cc85e87eaf05 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -149,29 +149,24 @@ static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, return ret; } +static int genpd_runtime_suspend(struct device *dev); + /* * Get the generic PM domain for a particular struct device. * This validates the struct device pointer, the PM domain pointer, * and checks that the PM domain pointer is a real generic PM domain. * Any failure results in NULL being returned. */ -static struct generic_pm_domain *genpd_lookup_dev(struct device *dev) +static struct generic_pm_domain *dev_to_genpd_safe(struct device *dev) { - struct generic_pm_domain *genpd = NULL, *gpd; - if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) return NULL; - mutex_lock(&gpd_list_lock); - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { - if (&gpd->domain == dev->pm_domain) { - genpd = gpd; - break; - } - } - mutex_unlock(&gpd_list_lock); + /* A genpd's always have its ->runtime_suspend() callback assigned. */ + if (dev->pm_domain->ops.runtime_suspend == genpd_runtime_suspend) + return pd_to_genpd(dev->pm_domain); - return genpd; + return NULL; } /* @@ -385,8 +380,8 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) unsigned int prev; int ret; - genpd = dev_to_genpd(dev); - if (IS_ERR(genpd)) + genpd = dev_to_genpd_safe(dev); + if (!genpd) return -ENODEV; if (unlikely(!genpd->set_performance_state)) @@ -1610,7 +1605,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, */ int pm_genpd_remove_device(struct device *dev) { - struct generic_pm_domain *genpd = genpd_lookup_dev(dev); + struct generic_pm_domain *genpd = dev_to_genpd_safe(dev); if (!genpd) return -EINVAL; diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 0ee8c0133d3e..3b7ffd0234e9 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -988,6 +988,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); INIT_LIST_HEAD(&opp_table->opp_list); kref_init(&opp_table->kref); + kref_init(&opp_table->list_kref); /* Secure the device table modification */ list_add(&opp_table->node, &opp_tables); @@ -1625,6 +1626,12 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, goto free_regulators; } + ret = regulator_enable(reg); + if (ret < 0) { + regulator_put(reg); + goto free_regulators; + } + opp_table->regulators[i] = reg; } @@ -1638,8 +1645,10 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, return opp_table; free_regulators: - while (i != 0) - regulator_put(opp_table->regulators[--i]); + while (i--) { + regulator_disable(opp_table->regulators[i]); + regulator_put(opp_table->regulators[i]); + } kfree(opp_table->regulators); opp_table->regulators = NULL; @@ -1665,8 +1674,10 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) /* Make sure there are no concurrent readers while updating opp_table */ WARN_ON(!list_empty(&opp_table->opp_list)); - for (i = opp_table->regulator_count - 1; i >= 0; i--) + for (i = opp_table->regulator_count - 1; i >= 0; i--) { + regulator_disable(opp_table->regulators[i]); regulator_put(opp_table->regulators[i]); + } _free_set_opp_data(opp_table); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index b313aca9894f..1813f5ad5fa2 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -617,9 +617,12 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, /* OPP to select on device suspend */ if (of_property_read_bool(np, "opp-suspend")) { if (opp_table->suspend_opp) { - dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n", - __func__, opp_table->suspend_opp->rate, - new_opp->rate); + /* Pick the OPP with higher rate as suspend OPP */ + if (new_opp->rate > opp_table->suspend_opp->rate) { + opp_table->suspend_opp->suspend = false; + new_opp->suspend = true; + opp_table->suspend_opp = new_opp; + } } else { new_opp->suspend = true; opp_table->suspend_opp = new_opp; @@ -662,8 +665,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) return 0; } - kref_init(&opp_table->list_kref); - /* We have opp-table node now, iterate over it and add OPPs */ for_each_available_child_of_node(opp_table->np, np) { opp = _opp_add_static_v2(opp_table, dev, np); @@ -672,17 +673,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, ret); of_node_put(np); - goto put_list_kref; + return ret; } else if (opp) { count++; } } /* There should be one of more OPP defined */ - if (WARN_ON(!count)) { - ret = -ENOENT; - goto put_list_kref; - } + if (WARN_ON(!count)) + return -ENOENT; list_for_each_entry(opp, &opp_table->opp_list, node) pstate_count += !!opp->pstate; @@ -691,8 +690,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) if (pstate_count && pstate_count != count) { dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", count, pstate_count); - ret = -ENOENT; - goto put_list_kref; + return -ENOENT; } if (pstate_count) @@ -701,11 +699,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) opp_table->parsed_static_opps = true; return 0; - -put_list_kref: - _put_opp_list_kref(opp_table); - - return ret; } /* Initializes OPP tables based on old-deprecated bindings */ @@ -731,8 +724,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) return -EINVAL; } - kref_init(&opp_table->list_kref); - val = prop->value; while (nr) { unsigned long freq = be32_to_cpup(val++) * 1000; @@ -742,7 +733,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) if (ret) { dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", __func__, freq, ret); - _put_opp_list_kref(opp_table); return ret; } nr -= 2; |