aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pmdomain/core.c125
-rw-r--r--drivers/pmdomain/imx/imx8m-blk-ctrl.c9
-rw-r--r--drivers/pmdomain/imx/imx8mp-blk-ctrl.c9
-rw-r--r--drivers/pmdomain/qcom/rpmpd.c13
-rw-r--r--drivers/pmdomain/renesas/r8a779a0-sysc.c12
-rw-r--r--drivers/pmdomain/renesas/r8a779f0-sysc.c12
-rw-r--r--drivers/pmdomain/renesas/r8a779g0-sysc.c12
-rw-r--r--drivers/pmdomain/ti/omap_prm.c2
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;