diff options
-rw-r--r-- | drivers/pmdomain/core.c | 125 | ||||
-rw-r--r-- | drivers/pmdomain/imx/imx8m-blk-ctrl.c | 9 | ||||
-rw-r--r-- | drivers/pmdomain/imx/imx8mp-blk-ctrl.c | 9 | ||||
-rw-r--r-- | drivers/pmdomain/qcom/rpmpd.c | 13 | ||||
-rw-r--r-- | drivers/pmdomain/renesas/r8a779a0-sysc.c | 12 | ||||
-rw-r--r-- | drivers/pmdomain/renesas/r8a779f0-sysc.c | 12 | ||||
-rw-r--r-- | drivers/pmdomain/renesas/r8a779g0-sysc.c | 12 | ||||
-rw-r--r-- | drivers/pmdomain/ti/omap_prm.c | 2 |
8 files changed, 98 insertions, 96 deletions
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 18e232b5ed53..46331e71108a 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -311,72 +311,102 @@ static int genpd_xlate_performance_state(struct generic_pm_domain *genpd, } static int _genpd_set_performance_state(struct generic_pm_domain *genpd, - unsigned int state, int depth) + unsigned int state, int depth); + +static void _genpd_rollback_parent_state(struct gpd_link *link, int depth) { - struct generic_pm_domain *parent; - struct gpd_link *link; - int parent_state, ret; + struct generic_pm_domain *parent = link->parent; + int parent_state; - if (state == genpd->performance_state) - return 0; + genpd_lock_nested(parent, depth + 1); - /* Propagate to parents of genpd */ - list_for_each_entry(link, &genpd->child_links, child_node) { - parent = link->parent; + parent_state = link->prev_performance_state; + link->performance_state = parent_state; - /* Find parent's performance state */ - ret = genpd_xlate_performance_state(genpd, parent, state); - if (unlikely(ret < 0)) - goto err; + parent_state = _genpd_reeval_performance_state(parent, parent_state); + if (_genpd_set_performance_state(parent, parent_state, depth + 1)) { + pr_err("%s: Failed to roll back to %d performance state\n", + parent->name, parent_state); + } - parent_state = ret; + genpd_unlock(parent); +} - genpd_lock_nested(parent, depth + 1); +static int _genpd_set_parent_state(struct generic_pm_domain *genpd, + struct gpd_link *link, + unsigned int state, int depth) +{ + struct generic_pm_domain *parent = link->parent; + int parent_state, ret; - link->prev_performance_state = link->performance_state; - link->performance_state = parent_state; - parent_state = _genpd_reeval_performance_state(parent, - parent_state); - ret = _genpd_set_performance_state(parent, parent_state, depth + 1); - if (ret) - link->performance_state = link->prev_performance_state; + /* Find parent's performance state */ + ret = genpd_xlate_performance_state(genpd, parent, state); + if (unlikely(ret < 0)) + return ret; - genpd_unlock(parent); + parent_state = ret; - if (ret) - goto err; - } + genpd_lock_nested(parent, depth + 1); - if (genpd->set_performance_state) { - ret = genpd->set_performance_state(genpd, state); - if (ret) - goto err; - } + link->prev_performance_state = link->performance_state; + link->performance_state = parent_state; - genpd->performance_state = state; - return 0; + parent_state = _genpd_reeval_performance_state(parent, parent_state); + ret = _genpd_set_performance_state(parent, parent_state, depth + 1); + if (ret) + link->performance_state = link->prev_performance_state; -err: - /* Encountered an error, lets rollback */ - list_for_each_entry_continue_reverse(link, &genpd->child_links, - child_node) { - parent = link->parent; + genpd_unlock(parent); - genpd_lock_nested(parent, depth + 1); + return ret; +} + +static int _genpd_set_performance_state(struct generic_pm_domain *genpd, + unsigned int state, int depth) +{ + struct gpd_link *link = NULL; + int ret; + + if (state == genpd->performance_state) + return 0; - parent_state = link->prev_performance_state; - link->performance_state = parent_state; + /* When scaling up, propagate to parents first in normal order */ + if (state > genpd->performance_state) { + list_for_each_entry(link, &genpd->child_links, child_node) { + ret = _genpd_set_parent_state(genpd, link, state, depth); + if (ret) + goto rollback_parents_up; + } + } - parent_state = _genpd_reeval_performance_state(parent, - parent_state); - if (_genpd_set_performance_state(parent, parent_state, depth + 1)) { - pr_err("%s: Failed to roll back to %d performance state\n", - parent->name, parent_state); + if (genpd->set_performance_state) { + ret = genpd->set_performance_state(genpd, state); + if (ret) { + if (link) + goto rollback_parents_up; + return ret; } + } - genpd_unlock(parent); + /* When scaling down, propagate to parents last in reverse order */ + if (state < genpd->performance_state) { + list_for_each_entry_reverse(link, &genpd->child_links, child_node) { + ret = _genpd_set_parent_state(genpd, link, state, depth); + if (ret) + goto rollback_parents_down; + } } + genpd->performance_state = state; + return 0; + +rollback_parents_up: + list_for_each_entry_continue_reverse(link, &genpd->child_links, child_node) + _genpd_rollback_parent_state(link, depth); + return ret; +rollback_parents_down: + list_for_each_entry_continue(link, &genpd->child_links, child_node) + _genpd_rollback_parent_state(link, depth); return ret; } @@ -1100,6 +1130,7 @@ static int __init genpd_power_off_unused(void) return 0; } + pr_info("genpd: Disabling unused power domains\n"); mutex_lock(&gpd_list_lock); list_for_each_entry(genpd, &gpd_list, gpd_list_node) diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c index 1341a707f61b..ca942d7929c2 100644 --- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c +++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c @@ -258,11 +258,14 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev) domain->power_dev = dev_pm_domain_attach_by_name(dev, data->gpc_name); - if (IS_ERR(domain->power_dev)) { - dev_err_probe(dev, PTR_ERR(domain->power_dev), + if (IS_ERR_OR_NULL(domain->power_dev)) { + if (!domain->power_dev) + ret = -ENODEV; + else + ret = PTR_ERR(domain->power_dev); + dev_err_probe(dev, ret, "failed to attach power domain \"%s\"\n", data->gpc_name); - ret = PTR_ERR(domain->power_dev); goto cleanup_pds; } diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c index e3203eb6a022..e488cf79b800 100644 --- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c +++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c @@ -687,11 +687,14 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) domain->power_dev = dev_pm_domain_attach_by_name(dev, data->gpc_name); - if (IS_ERR(domain->power_dev)) { - dev_err_probe(dev, PTR_ERR(domain->power_dev), + if (IS_ERR_OR_NULL(domain->power_dev)) { + if (!domain->power_dev) + ret = -ENODEV; + else + ret = PTR_ERR(domain->power_dev); + dev_err_probe(dev, ret, "failed to attach power domain %s\n", data->gpc_name); - ret = PTR_ERR(domain->power_dev); goto cleanup_pds; } diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c index 7796d65f96e8..90b62767f9d0 100644 --- a/drivers/pmdomain/qcom/rpmpd.c +++ b/drivers/pmdomain/qcom/rpmpd.c @@ -16,6 +16,8 @@ #define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd) +static struct qcom_smd_rpm *rpmpd_smd_rpm; + /* Resource types: * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ #define RPMPD_SMPA 0x61706d73 @@ -54,7 +56,6 @@ struct rpmpd { bool enabled; const int res_type; const int res_id; - struct qcom_smd_rpm *rpm; unsigned int max_state; __le32 key; bool state_synced; @@ -879,7 +880,7 @@ static int rpmpd_send_enable(struct rpmpd *pd, bool enable) .value = cpu_to_le32(enable), }; - return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + return qcom_rpm_smd_write(rpmpd_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, pd->res_type, pd->res_id, &req, sizeof(req)); } @@ -891,7 +892,7 @@ static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner) .value = cpu_to_le32(corner), }; - return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id, + return qcom_rpm_smd_write(rpmpd_smd_rpm, state, pd->res_type, pd->res_id, &req, sizeof(req)); }; @@ -1004,12 +1005,11 @@ static int rpmpd_probe(struct platform_device *pdev) int i; size_t num; struct genpd_onecell_data *data; - struct qcom_smd_rpm *rpm; struct rpmpd **rpmpds; const struct rpmpd_desc *desc; - rpm = dev_get_drvdata(pdev->dev.parent); - if (!rpm) { + rpmpd_smd_rpm = dev_get_drvdata(pdev->dev.parent); + if (!rpmpd_smd_rpm) { dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); return -ENODEV; } @@ -1039,7 +1039,6 @@ static int rpmpd_probe(struct platform_device *pdev) continue; } - rpmpds[i]->rpm = rpm; rpmpds[i]->max_state = desc->max_state; rpmpds[i]->pd.power_off = rpmpd_power_off; rpmpds[i]->pd.power_on = rpmpd_power_on; diff --git a/drivers/pmdomain/renesas/r8a779a0-sysc.c b/drivers/pmdomain/renesas/r8a779a0-sysc.c index 04f1bc322ae7..54cdf250f7c2 100644 --- a/drivers/pmdomain/renesas/r8a779a0-sysc.c +++ b/drivers/pmdomain/renesas/r8a779a0-sysc.c @@ -5,19 +5,7 @@ * Copyright (C) 2020 Renesas Electronics Corp. */ -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> #include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> #include <dt-bindings/power/r8a779a0-sysc.h> diff --git a/drivers/pmdomain/renesas/r8a779f0-sysc.c b/drivers/pmdomain/renesas/r8a779f0-sysc.c index 5602aa6bd7ed..6ed13cd1cb24 100644 --- a/drivers/pmdomain/renesas/r8a779f0-sysc.c +++ b/drivers/pmdomain/renesas/r8a779f0-sysc.c @@ -5,19 +5,7 @@ * Copyright (C) 2021 Renesas Electronics Corp. */ -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> #include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> #include <dt-bindings/power/r8a779f0-sysc.h> diff --git a/drivers/pmdomain/renesas/r8a779g0-sysc.c b/drivers/pmdomain/renesas/r8a779g0-sysc.c index b932eba1b804..249cf43af45b 100644 --- a/drivers/pmdomain/renesas/r8a779g0-sysc.c +++ b/drivers/pmdomain/renesas/r8a779g0-sysc.c @@ -5,19 +5,7 @@ * Copyright (C) 2022 Renesas Electronics Corp. */ -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> #include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> #include <dt-bindings/power/r8a779g0-sysc.h> diff --git a/drivers/pmdomain/ti/omap_prm.c b/drivers/pmdomain/ti/omap_prm.c index c2feae3a634c..b8ceb3c2b81c 100644 --- a/drivers/pmdomain/ti/omap_prm.c +++ b/drivers/pmdomain/ti/omap_prm.c @@ -695,6 +695,8 @@ static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm) data = prm->data; name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s", data->name); + if (!name) + return -ENOMEM; prmd->dev = dev; prmd->prm = prm; |