Commit f551592f authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'icc-6.3-rc3' of...

Merge tag 'icc-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc into char-misc-linus

Georgi writes:

interconnect fixes for v6.3-rc

This contains a bunch of fixes with the highlight being fixes for a race
condition that could sometimes occur during the interconnect provider
driver registration. There are also fixes for memory overallocation and
a memory leak.

- interconnect: qcom: osm-l3: fix icc_onecell_data allocation
- interconnect: qcom: sm8450: switch to qcom_icc_rpmh_* function
- interconnect: qcom: sm8550: switch to qcom_icc_rpmh_* function
- interconnect: qcom: qcm2290: Fix MASTER_SNOC_BIMC_NRT
- interconnect: fix mem leak when freeing nodes
- interconnect: fix icc_provider_del() error handling
- interconnect: fix provider registration API
- interconnect: imx: fix registration race
- interconnect: qcom: osm-l3: fix registration race
- interconnect: qcom: rpm: fix probe child-node error handling
- interconnect: qcom: rpm: fix registration race
- interconnect: qcom: rpmh: fix probe child-node error handling
- interconnect: qcom: rpmh: fix registration race
- interconnect: qcom: msm8974: fix registration race
- interconnect: exynos: fix node leak in probe PM QoS error path
- interconnect: exynos: fix registration race
- interconnect: exynos: drop redundant link destroy
- memory: tegra: fix interconnect registration race
- memory: tegra124-emc: fix interconnect registration race
- memory: tegra20-emc: fix interconnect registration race
- memory: tegra30-emc: fix interconnect registration race
Signed-off-by: default avatarGeorgi Djakov <djakov@kernel.org>

* tag 'icc-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc: (21 commits)
  memory: tegra30-emc: fix interconnect registration race
  memory: tegra20-emc: fix interconnect registration race
  memory: tegra124-emc: fix interconnect registration race
  memory: tegra: fix interconnect registration race
  interconnect: exynos: drop redundant link destroy
  interconnect: exynos: fix registration race
  interconnect: exynos: fix node leak in probe PM QoS error path
  interconnect: qcom: msm8974: fix registration race
  interconnect: qcom: rpmh: fix registration race
  interconnect: qcom: rpmh: fix probe child-node error handling
  interconnect: qcom: rpm: fix registration race
  interconnect: qcom: rpm: fix probe child-node error handling
  interconnect: qcom: osm-l3: fix registration race
  interconnect: imx: fix registration race
  interconnect: fix provider registration API
  interconnect: fix icc_provider_del() error handling
  interconnect: fix mem leak when freeing nodes
  interconnect: qcom: qcm2290: Fix MASTER_SNOC_BIMC_NRT
  interconnect: qcom: sm8550: switch to qcom_icc_rpmh_* function
  interconnect: qcom: sm8450: switch to qcom_icc_rpmh_* function
  ...
parents 06be6208 9db481c9
......@@ -850,6 +850,10 @@ void icc_node_destroy(int id)
mutex_unlock(&icc_lock);
if (!node)
return;
kfree(node->links);
kfree(node);
}
EXPORT_SYMBOL_GPL(icc_node_destroy);
......@@ -1029,54 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider)
EXPORT_SYMBOL_GPL(icc_nodes_remove);
/**
* icc_provider_add() - add a new interconnect provider
* @provider: the interconnect provider that will be added into topology
* icc_provider_init() - initialize a new interconnect provider
* @provider: the interconnect provider to initialize
*
* Must be called before adding nodes to the provider.
*/
void icc_provider_init(struct icc_provider *provider)
{
WARN_ON(!provider->set);
INIT_LIST_HEAD(&provider->nodes);
}
EXPORT_SYMBOL_GPL(icc_provider_init);
/**
* icc_provider_register() - register a new interconnect provider
* @provider: the interconnect provider to register
*
* Return: 0 on success, or an error code otherwise
*/
int icc_provider_add(struct icc_provider *provider)
int icc_provider_register(struct icc_provider *provider)
{
if (WARN_ON(!provider->set))
return -EINVAL;
if (WARN_ON(!provider->xlate && !provider->xlate_extended))
return -EINVAL;
mutex_lock(&icc_lock);
INIT_LIST_HEAD(&provider->nodes);
list_add_tail(&provider->provider_list, &icc_providers);
mutex_unlock(&icc_lock);
dev_dbg(provider->dev, "interconnect provider added to topology\n");
dev_dbg(provider->dev, "interconnect provider registered\n");
return 0;
}
EXPORT_SYMBOL_GPL(icc_provider_add);
EXPORT_SYMBOL_GPL(icc_provider_register);
/**
* icc_provider_del() - delete previously added interconnect provider
* @provider: the interconnect provider that will be removed from topology
* icc_provider_deregister() - deregister an interconnect provider
* @provider: the interconnect provider to deregister
*/
void icc_provider_del(struct icc_provider *provider)
void icc_provider_deregister(struct icc_provider *provider)
{
mutex_lock(&icc_lock);
if (provider->users) {
pr_warn("interconnect provider still has %d users\n",
provider->users);
mutex_unlock(&icc_lock);
return;
}
if (!list_empty(&provider->nodes)) {
pr_warn("interconnect provider still has nodes\n");
mutex_unlock(&icc_lock);
return;
}
WARN_ON(provider->users);
list_del(&provider->provider_list);
mutex_unlock(&icc_lock);
}
EXPORT_SYMBOL_GPL(icc_provider_deregister);
int icc_provider_add(struct icc_provider *provider)
{
icc_provider_init(provider);
return icc_provider_register(provider);
}
EXPORT_SYMBOL_GPL(icc_provider_add);
void icc_provider_del(struct icc_provider *provider)
{
WARN_ON(!list_empty(&provider->nodes));
icc_provider_deregister(provider);
}
EXPORT_SYMBOL_GPL(icc_provider_del);
static const struct of_device_id __maybe_unused ignore_list[] = {
......
......@@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev,
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
provider->dev = dev->parent;
icc_provider_init(provider);
platform_set_drvdata(pdev, imx_provider);
if (settings) {
......@@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev,
}
}
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
if (ret)
return ret;
}
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
ret = icc_provider_register(provider);
if (ret)
goto provider_del;
goto err_unregister_nodes;
return 0;
provider_del:
icc_provider_del(provider);
err_unregister_nodes:
imx_icc_unregister_nodes(&imx_provider->provider);
return ret;
}
EXPORT_SYMBOL_GPL(imx_icc_register);
......@@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev)
{
struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
icc_provider_deregister(&imx_provider->provider);
imx_icc_unregister_nodes(&imx_provider->provider);
icc_provider_del(&imx_provider->provider);
}
EXPORT_SYMBOL_GPL(imx_icc_unregister);
......
......@@ -503,7 +503,6 @@ int qnoc_probe(struct platform_device *pdev)
}
provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = qcom_icc_set;
provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
......@@ -511,12 +510,7 @@ int qnoc_probe(struct platform_device *pdev)
provider->xlate_extended = qcom_icc_xlate_extended;
provider->data = data;
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
}
icc_provider_init(provider);
for (i = 0; i < num_nodes; i++) {
size_t j;
......@@ -524,7 +518,7 @@ int qnoc_probe(struct platform_device *pdev)
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err;
goto err_remove_nodes;
}
node->name = qnodes[i]->name;
......@@ -538,17 +532,26 @@ int qnoc_probe(struct platform_device *pdev)
}
data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp);
/* Populate child NoC devices if any */
if (of_get_child_count(dev->of_node) > 0)
return of_platform_populate(dev->of_node, NULL, NULL, dev);
if (of_get_child_count(dev->of_node) > 0) {
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret)
goto err_deregister_provider;
}
return 0;
err:
err_deregister_provider:
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(provider);
return ret;
}
......@@ -558,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(&qp->provider);
return 0;
}
......
......@@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
provider->pre_aggregate = qcom_icc_pre_aggregate;
provider->aggregate = qcom_icc_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data;
icc_provider_init(provider);
qp->dev = dev;
qp->bcms = desc->bcms;
qp->num_bcms = desc->num_bcms;
......@@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
if (IS_ERR(qp->voter))
return PTR_ERR(qp->voter);
ret = icc_provider_add(provider);
if (ret)
return ret;
for (i = 0; i < qp->num_bcms; i++)
qcom_icc_bcm_init(qp->bcms[i], dev);
......@@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
node = icc_node_create(qn->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err;
goto err_remove_nodes;
}
node->name = qn->name;
......@@ -232,16 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
}
data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp);
/* Populate child NoC devices if any */
if (of_get_child_count(dev->of_node) > 0)
return of_platform_populate(dev->of_node, NULL, NULL, dev);
if (of_get_child_count(dev->of_node) > 0) {
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret)
goto err_deregister_provider;
}
return 0;
err:
err_deregister_provider:
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider);
icc_provider_del(provider);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe);
......@@ -250,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0;
}
......
......@@ -692,7 +692,6 @@ static int msm8974_icc_probe(struct platform_device *pdev)
return ret;
provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = msm8974_icc_set;
provider->aggregate = icc_std_aggregate;
......@@ -700,11 +699,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
provider->data = data;
provider->get_bw = msm8974_get_bw;
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
goto err_disable_clks;
}
icc_provider_init(provider);
for (i = 0; i < num_nodes; i++) {
size_t j;
......@@ -712,7 +707,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err_del_icc;
goto err_remove_nodes;
}
node->name = qnodes[i]->name;
......@@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev)
}
data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err_del_icc:
err_remove_nodes:
icc_nodes_remove(provider);
icc_provider_del(provider);
err_disable_clks:
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
......@@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
{
struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(&qp->provider);
return 0;
}
......
......@@ -158,8 +158,8 @@ static int qcom_osm_l3_remove(struct platform_device *pdev)
{
struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0;
}
......@@ -236,7 +236,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
data = devm_kzalloc(&pdev->dev, struct_size(data, nodes, num_nodes), GFP_KERNEL);
if (!data)
return -ENOMEM;
......@@ -245,14 +245,9 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
provider->set = qcom_osm_l3_set;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data;
ret = icc_provider_add(provider);
if (ret) {
dev_err(&pdev->dev, "error adding interconnect provider\n");
return ret;
}
icc_provider_init(provider);
for (i = 0; i < num_nodes; i++) {
size_t j;
......@@ -275,12 +270,15 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
}
data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err;
platform_set_drvdata(pdev, qp);
return 0;
err:
icc_nodes_remove(provider);
icc_provider_del(provider);
return ret;
}
......
......@@ -147,9 +147,9 @@ static struct qcom_icc_node mas_snoc_bimc_nrt = {
.name = "mas_snoc_bimc_nrt",
.buswidth = 16,
.qos.ap_owned = true,
.qos.qos_port = 2,
.qos.qos_port = 3,
.qos.qos_mode = NOC_QOS_MODE_BYPASS,
.mas_rpm_id = 163,
.mas_rpm_id = 164,
.slv_rpm_id = -1,
.num_links = ARRAY_SIZE(mas_snoc_bimc_nrt_links),
.links = mas_snoc_bimc_nrt_links,
......
......@@ -1844,100 +1844,6 @@ static const struct qcom_icc_desc sm8450_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
static int qnoc_probe(struct platform_device *pdev)
{
const struct qcom_icc_desc *desc;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct qcom_icc_node * const *qnodes;
struct qcom_icc_provider *qp;
struct icc_node *node;
size_t num_nodes, i;
int ret;
desc = device_get_match_data(&pdev->dev);
if (!desc)
return -EINVAL;
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
if (!data)
return -ENOMEM;
provider = &qp->provider;
provider->dev = &pdev->dev;
provider->set = qcom_icc_set;
provider->pre_aggregate = qcom_icc_pre_aggregate;
provider->aggregate = qcom_icc_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data;
qp->dev = &pdev->dev;
qp->bcms = desc->bcms;
qp->num_bcms = desc->num_bcms;
qp->voter = of_bcm_voter_get(qp->dev, NULL);
if (IS_ERR(qp->voter))
return PTR_ERR(qp->voter);
ret = icc_provider_add(provider);
if (ret) {
dev_err(&pdev->dev, "error adding interconnect provider\n");
return ret;
}
for (i = 0; i < qp->num_bcms; i++)
qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
for (i = 0; i < num_nodes; i++) {
size_t j;
if (!qnodes[i])
continue;
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err;
}
node->name = qnodes[i]->name;
node->data = qnodes[i];
icc_node_add(node, provider);
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err:
icc_nodes_remove(provider);
icc_provider_del(provider);
return ret;
}
static int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0;
}
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8450-aggre1-noc",
.data = &sm8450_aggre1_noc},
......@@ -1966,8 +1872,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
.remove = qnoc_remove,
.probe = qcom_icc_rpmh_probe,
.remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8450",
.of_match_table = qnoc_of_match,
......
......@@ -2165,101 +2165,6 @@ static const struct qcom_icc_desc sm8550_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
static int qnoc_probe(struct platform_device *pdev)
{
const struct qcom_icc_desc *desc;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct qcom_icc_node * const *qnodes;
struct qcom_icc_provider *qp;
struct icc_node *node;
size_t num_nodes, i;
int ret;
desc = device_get_match_data(&pdev->dev);
if (!desc)
return -EINVAL;
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
if (!data)
return -ENOMEM;
provider = &qp->provider;
provider->dev = &pdev->dev;
provider->set = qcom_icc_set;
provider->pre_aggregate = qcom_icc_pre_aggregate;
provider->aggregate = qcom_icc_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data;
qp->dev = &pdev->dev;
qp->bcms = desc->bcms;
qp->num_bcms = desc->num_bcms;
qp->voter = of_bcm_voter_get(qp->dev, NULL);
if (IS_ERR(qp->voter))
return PTR_ERR(qp->voter);
ret = icc_provider_add(provider);
if (ret) {
dev_err_probe(&pdev->dev, ret,
"error adding interconnect provider\n");
return ret;
}
for (i = 0; i < qp->num_bcms; i++)
qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
for (i = 0; i < num_nodes; i++) {
size_t j;
if (!qnodes[i])
continue;
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err;
}
node->name = qnodes[i]->name;
node->data = qnodes[i];
icc_node_add(node, provider);
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err:
icc_nodes_remove(provider);
icc_provider_del(provider);
return ret;
}
static int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0;
}
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8550-aggre1-noc",
.data = &sm8550_aggre1_noc},
......@@ -2294,8 +2199,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
.remove = qnoc_remove,
.probe = qcom_icc_rpmh_probe,
.remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8550",
.of_match_table = qnoc_of_match,
......
......@@ -96,14 +96,9 @@ static struct icc_node *exynos_generic_icc_xlate(struct of_phandle_args *spec,
static int exynos_generic_icc_remove(struct platform_device *pdev)
{
struct exynos_icc_priv *priv = platform_get_drvdata(pdev);
struct icc_node *parent_node, *node = priv->node;
parent_node = exynos_icc_get_parent(priv->dev->parent->of_node);
if (parent_node && !IS_ERR(parent_node))
icc_link_destroy(node, parent_node);
icc_provider_deregister(&priv->provider);
icc_nodes_remove(&priv->provider);
icc_provider_del(&priv->provider);
return 0;
}
......@@ -132,15 +127,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
provider->inter_set = true;
provider->data = priv;
ret = icc_provider_add(provider);
if (ret < 0)
return ret;
icc_provider_init(provider);
icc_node = icc_node_create(pdev->id);
if (IS_ERR(icc_node)) {
ret = PTR_ERR(icc_node);
goto err_prov_del;
}
if (IS_ERR(icc_node))
return PTR_ERR(icc_node);
priv->node = icc_node;
icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn",
......@@ -149,6 +140,9 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
&priv->bus_clk_ratio))
priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_BUS_CLK_RATIO;
icc_node->data = priv;
icc_node_add(icc_node, provider);
/*
* Register a PM QoS request for the parent (devfreq) device.
*/
......@@ -157,9 +151,6 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_node_del;
icc_node->data = priv;
icc_node_add(icc_node, provider);
icc_parent_node = exynos_icc_get_parent(bus_dev->of_node);
if (IS_ERR(icc_parent_node)) {
ret = PTR_ERR(icc_parent_node);
......@@ -171,14 +162,17 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
goto err_pmqos_del;
}
ret = icc_provider_register(provider);
if (ret < 0)
goto err_pmqos_del;
return 0;
err_pmqos_del:
dev_pm_qos_remove_request(&priv->qos_req);
err_node_del:
icc_nodes_remove(provider);
err_prov_del:
icc_provider_del(provider);
return ret;
}
......
......@@ -794,16 +794,12 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
mc->provider.aggregate = mc->soc->icc_ops->aggregate;
mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
err = icc_provider_add(&mc->provider);
if (err)
return err;
icc_provider_init(&mc->provider);
/* create Memory Controller node */
node = icc_node_create(TEGRA_ICC_MC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
}
if (IS_ERR(node))
return PTR_ERR(node);
node->name = "Memory Controller";
icc_node_add(node, &mc->provider);
......@@ -830,12 +826,14 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
goto remove_nodes;
}
err = icc_provider_register(&mc->provider);
if (err)
goto remove_nodes;
return 0;
remove_nodes:
icc_nodes_remove(&mc->provider);
del_provider:
icc_provider_del(&mc->provider);
return err;
}
......
......@@ -1351,15 +1351,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider);
if (err)
goto err_msg;
icc_provider_init(&emc->provider);
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
goto err_msg;
}
node->name = "External Memory Controller";
......@@ -1380,12 +1378,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0;
remove_nodes:
icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
......
......@@ -1021,15 +1021,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider);
if (err)
goto err_msg;
icc_provider_init(&emc->provider);
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
goto err_msg;
}
node->name = "External Memory Controller";
......@@ -1050,12 +1048,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0;
remove_nodes:
icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
......
......@@ -1533,15 +1533,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider);
if (err)
goto err_msg;
icc_provider_init(&emc->provider);
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
goto err_msg;
}
node->name = "External Memory Controller";
......@@ -1562,12 +1560,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0;
remove_nodes:
icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
......
......@@ -122,6 +122,9 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst);
void icc_node_add(struct icc_node *node, struct icc_provider *provider);
void icc_node_del(struct icc_node *node);
int icc_nodes_remove(struct icc_provider *provider);
void icc_provider_init(struct icc_provider *provider);
int icc_provider_register(struct icc_provider *provider);
void icc_provider_deregister(struct icc_provider *provider);
int icc_provider_add(struct icc_provider *provider);
void icc_provider_del(struct icc_provider *provider);
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
......@@ -167,6 +170,15 @@ static inline int icc_nodes_remove(struct icc_provider *provider)
return -ENOTSUPP;
}
static inline void icc_provider_init(struct icc_provider *provider) { }
static inline int icc_provider_register(struct icc_provider *provider)
{
return -ENOTSUPP;
}
static inline void icc_provider_deregister(struct icc_provider *provider) { }
static inline int icc_provider_add(struct icc_provider *provider)
{
return -ENOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment