Commit ce86beb4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver fixes from Greg KH:
 "Here are a few small char/misc/other driver subsystem patches to
  resolve reported problems for 6.3-rc3.

  Included in here are:

   - Interconnect driver fixes for reported problems

   - Memory driver fixes for reported problems

   - nvmem core fix

   - firmware driver fix for reported problem

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (23 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
  nvmem: core: return -ENOENT if nvmem cell is not found
  firmware: xilinx: don't make a sleepable memory allocation from an atomic context
  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
  ...
parents c46a7d04 f551592f
...@@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id) ...@@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id)
} }
/* Add new entry if not present */ /* Add new entry if not present */
feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL); feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
if (!feature_data) if (!feature_data)
return -ENOMEM; return -ENOMEM;
......
...@@ -850,6 +850,10 @@ void icc_node_destroy(int id) ...@@ -850,6 +850,10 @@ void icc_node_destroy(int id)
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
if (!node)
return;
kfree(node->links);
kfree(node); kfree(node);
} }
EXPORT_SYMBOL_GPL(icc_node_destroy); EXPORT_SYMBOL_GPL(icc_node_destroy);
...@@ -1029,54 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider) ...@@ -1029,54 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider)
EXPORT_SYMBOL_GPL(icc_nodes_remove); EXPORT_SYMBOL_GPL(icc_nodes_remove);
/** /**
* icc_provider_add() - add a new interconnect provider * icc_provider_init() - initialize a new interconnect provider
* @provider: the interconnect provider that will be added into topology * @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 * 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)) if (WARN_ON(!provider->xlate && !provider->xlate_extended))
return -EINVAL; return -EINVAL;
mutex_lock(&icc_lock); mutex_lock(&icc_lock);
INIT_LIST_HEAD(&provider->nodes);
list_add_tail(&provider->provider_list, &icc_providers); list_add_tail(&provider->provider_list, &icc_providers);
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
dev_dbg(provider->dev, "interconnect provider added to topology\n"); dev_dbg(provider->dev, "interconnect provider registered\n");
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(icc_provider_add); EXPORT_SYMBOL_GPL(icc_provider_register);
/** /**
* icc_provider_del() - delete previously added interconnect provider * icc_provider_deregister() - deregister an interconnect provider
* @provider: the interconnect provider that will be removed from topology * @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); mutex_lock(&icc_lock);
if (provider->users) { WARN_ON(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;
}
list_del(&provider->provider_list); list_del(&provider->provider_list);
mutex_unlock(&icc_lock); 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); EXPORT_SYMBOL_GPL(icc_provider_del);
static const struct of_device_id __maybe_unused ignore_list[] = { static const struct of_device_id __maybe_unused ignore_list[] = {
......
...@@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev, ...@@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev,
provider->xlate = of_icc_xlate_onecell; provider->xlate = of_icc_xlate_onecell;
provider->data = data; provider->data = data;
provider->dev = dev->parent; provider->dev = dev->parent;
icc_provider_init(provider);
platform_set_drvdata(pdev, imx_provider); platform_set_drvdata(pdev, imx_provider);
if (settings) { if (settings) {
...@@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev, ...@@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev,
} }
} }
ret = icc_provider_add(provider); ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
if (ret) { if (ret)
dev_err(dev, "error adding interconnect provider: %d\n", ret);
return ret; return ret;
}
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings); ret = icc_provider_register(provider);
if (ret) if (ret)
goto provider_del; goto err_unregister_nodes;
return 0; return 0;
provider_del: err_unregister_nodes:
icc_provider_del(provider); imx_icc_unregister_nodes(&imx_provider->provider);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(imx_icc_register); EXPORT_SYMBOL_GPL(imx_icc_register);
...@@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev) ...@@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev)
{ {
struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev); struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
icc_provider_deregister(&imx_provider->provider);
imx_icc_unregister_nodes(&imx_provider->provider); imx_icc_unregister_nodes(&imx_provider->provider);
icc_provider_del(&imx_provider->provider);
} }
EXPORT_SYMBOL_GPL(imx_icc_unregister); EXPORT_SYMBOL_GPL(imx_icc_unregister);
......
...@@ -503,7 +503,6 @@ int qnoc_probe(struct platform_device *pdev) ...@@ -503,7 +503,6 @@ int qnoc_probe(struct platform_device *pdev)
} }
provider = &qp->provider; provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev; provider->dev = dev;
provider->set = qcom_icc_set; provider->set = qcom_icc_set;
provider->pre_aggregate = qcom_icc_pre_bw_aggregate; provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
...@@ -511,12 +510,7 @@ int qnoc_probe(struct platform_device *pdev) ...@@ -511,12 +510,7 @@ int qnoc_probe(struct platform_device *pdev)
provider->xlate_extended = qcom_icc_xlate_extended; provider->xlate_extended = qcom_icc_xlate_extended;
provider->data = data; provider->data = data;
ret = icc_provider_add(provider); icc_provider_init(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;
}
for (i = 0; i < num_nodes; i++) { for (i = 0; i < num_nodes; i++) {
size_t j; size_t j;
...@@ -524,7 +518,7 @@ int qnoc_probe(struct platform_device *pdev) ...@@ -524,7 +518,7 @@ int qnoc_probe(struct platform_device *pdev)
node = icc_node_create(qnodes[i]->id); node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) { if (IS_ERR(node)) {
ret = PTR_ERR(node); ret = PTR_ERR(node);
goto err; goto err_remove_nodes;
} }
node->name = qnodes[i]->name; node->name = qnodes[i]->name;
...@@ -538,17 +532,26 @@ int qnoc_probe(struct platform_device *pdev) ...@@ -538,17 +532,26 @@ int qnoc_probe(struct platform_device *pdev)
} }
data->num_nodes = num_nodes; data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp); platform_set_drvdata(pdev, qp);
/* Populate child NoC devices if any */ /* Populate child NoC devices if any */
if (of_get_child_count(dev->of_node) > 0) if (of_get_child_count(dev->of_node) > 0) {
return of_platform_populate(dev->of_node, NULL, NULL, dev); ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret)
goto err_deregister_provider;
}
return 0; return 0;
err:
err_deregister_provider:
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider); icc_nodes_remove(provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(provider);
return ret; return ret;
} }
...@@ -558,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev) ...@@ -558,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev)
{ {
struct qcom_icc_provider *qp = platform_get_drvdata(pdev); struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider); icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(&qp->provider);
return 0; return 0;
} }
......
...@@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) ...@@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
provider->pre_aggregate = qcom_icc_pre_aggregate; provider->pre_aggregate = qcom_icc_pre_aggregate;
provider->aggregate = qcom_icc_aggregate; provider->aggregate = qcom_icc_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended; provider->xlate_extended = qcom_icc_xlate_extended;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data; provider->data = data;
icc_provider_init(provider);
qp->dev = dev; qp->dev = dev;
qp->bcms = desc->bcms; qp->bcms = desc->bcms;
qp->num_bcms = desc->num_bcms; qp->num_bcms = desc->num_bcms;
...@@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) ...@@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
if (IS_ERR(qp->voter)) if (IS_ERR(qp->voter))
return PTR_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++) for (i = 0; i < qp->num_bcms; i++)
qcom_icc_bcm_init(qp->bcms[i], dev); qcom_icc_bcm_init(qp->bcms[i], dev);
...@@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) ...@@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
node = icc_node_create(qn->id); node = icc_node_create(qn->id);
if (IS_ERR(node)) { if (IS_ERR(node)) {
ret = PTR_ERR(node); ret = PTR_ERR(node);
goto err; goto err_remove_nodes;
} }
node->name = qn->name; node->name = qn->name;
...@@ -232,16 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) ...@@ -232,16 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
} }
data->num_nodes = num_nodes; data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp); platform_set_drvdata(pdev, qp);
/* Populate child NoC devices if any */ /* Populate child NoC devices if any */
if (of_get_child_count(dev->of_node) > 0) if (of_get_child_count(dev->of_node) > 0) {
return of_platform_populate(dev->of_node, NULL, NULL, dev); ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret)
goto err_deregister_provider;
}
return 0; return 0;
err:
err_deregister_provider:
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider); icc_nodes_remove(provider);
icc_provider_del(provider);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe); EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe);
...@@ -250,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev) ...@@ -250,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
{ {
struct qcom_icc_provider *qp = platform_get_drvdata(pdev); struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider); icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0; return 0;
} }
......
...@@ -692,7 +692,6 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -692,7 +692,6 @@ static int msm8974_icc_probe(struct platform_device *pdev)
return ret; return ret;
provider = &qp->provider; provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev; provider->dev = dev;
provider->set = msm8974_icc_set; provider->set = msm8974_icc_set;
provider->aggregate = icc_std_aggregate; provider->aggregate = icc_std_aggregate;
...@@ -700,11 +699,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -700,11 +699,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
provider->data = data; provider->data = data;
provider->get_bw = msm8974_get_bw; provider->get_bw = msm8974_get_bw;
ret = icc_provider_add(provider); icc_provider_init(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
goto err_disable_clks;
}
for (i = 0; i < num_nodes; i++) { for (i = 0; i < num_nodes; i++) {
size_t j; size_t j;
...@@ -712,7 +707,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -712,7 +707,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
node = icc_node_create(qnodes[i]->id); node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) { if (IS_ERR(node)) {
ret = PTR_ERR(node); ret = PTR_ERR(node);
goto err_del_icc; goto err_remove_nodes;
} }
node->name = qnodes[i]->name; node->name = qnodes[i]->name;
...@@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev)
} }
data->num_nodes = num_nodes; data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
platform_set_drvdata(pdev, qp); platform_set_drvdata(pdev, qp);
return 0; return 0;
err_del_icc: err_remove_nodes:
icc_nodes_remove(provider); icc_nodes_remove(provider);
icc_provider_del(provider);
err_disable_clks:
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret; return ret;
...@@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev) ...@@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
{ {
struct msm8974_icc_provider *qp = platform_get_drvdata(pdev); struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider); icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(&qp->provider);
return 0; return 0;
} }
......
...@@ -158,8 +158,8 @@ static int qcom_osm_l3_remove(struct platform_device *pdev) ...@@ -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); struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev);
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider); icc_nodes_remove(&qp->provider);
icc_provider_del(&qp->provider);
return 0; return 0;
} }
...@@ -236,7 +236,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) ...@@ -236,7 +236,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
qnodes = desc->nodes; qnodes = desc->nodes;
num_nodes = desc->num_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) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -245,14 +245,9 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) ...@@ -245,14 +245,9 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
provider->set = qcom_osm_l3_set; provider->set = qcom_osm_l3_set;
provider->aggregate = icc_std_aggregate; provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell; provider->xlate = of_icc_xlate_onecell;
INIT_LIST_HEAD(&provider->nodes);
provider->data = data; provider->data = data;
ret = icc_provider_add(provider); icc_provider_init(provider);
if (ret) {
dev_err(&pdev->dev, "error adding interconnect provider\n");
return ret;
}
for (i = 0; i < num_nodes; i++) { for (i = 0; i < num_nodes; i++) {
size_t j; size_t j;
...@@ -275,12 +270,15 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) ...@@ -275,12 +270,15 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
} }
data->num_nodes = num_nodes; data->num_nodes = num_nodes;
ret = icc_provider_register(provider);
if (ret)
goto err;
platform_set_drvdata(pdev, qp); platform_set_drvdata(pdev, qp);
return 0; return 0;
err: err:
icc_nodes_remove(provider); icc_nodes_remove(provider);
icc_provider_del(provider);
return ret; return ret;
} }
......
...@@ -147,9 +147,9 @@ static struct qcom_icc_node mas_snoc_bimc_nrt = { ...@@ -147,9 +147,9 @@ static struct qcom_icc_node mas_snoc_bimc_nrt = {
.name = "mas_snoc_bimc_nrt", .name = "mas_snoc_bimc_nrt",
.buswidth = 16, .buswidth = 16,
.qos.ap_owned = true, .qos.ap_owned = true,
.qos.qos_port = 2, .qos.qos_port = 3,
.qos.qos_mode = NOC_QOS_MODE_BYPASS, .qos.qos_mode = NOC_QOS_MODE_BYPASS,
.mas_rpm_id = 163, .mas_rpm_id = 164,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.num_links = ARRAY_SIZE(mas_snoc_bimc_nrt_links), .num_links = ARRAY_SIZE(mas_snoc_bimc_nrt_links),
.links = mas_snoc_bimc_nrt_links, .links = mas_snoc_bimc_nrt_links,
......
...@@ -1844,100 +1844,6 @@ static const struct qcom_icc_desc sm8450_system_noc = { ...@@ -1844,100 +1844,6 @@ static const struct qcom_icc_desc sm8450_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms), .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[] = { static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8450-aggre1-noc", { .compatible = "qcom,sm8450-aggre1-noc",
.data = &sm8450_aggre1_noc}, .data = &sm8450_aggre1_noc},
...@@ -1966,8 +1872,8 @@ static const struct of_device_id qnoc_of_match[] = { ...@@ -1966,8 +1872,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match); MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = { static struct platform_driver qnoc_driver = {
.probe = qnoc_probe, .probe = qcom_icc_rpmh_probe,
.remove = qnoc_remove, .remove = qcom_icc_rpmh_remove,
.driver = { .driver = {
.name = "qnoc-sm8450", .name = "qnoc-sm8450",
.of_match_table = qnoc_of_match, .of_match_table = qnoc_of_match,
......
...@@ -2165,101 +2165,6 @@ static const struct qcom_icc_desc sm8550_system_noc = { ...@@ -2165,101 +2165,6 @@ static const struct qcom_icc_desc sm8550_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms), .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[] = { static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,sm8550-aggre1-noc", { .compatible = "qcom,sm8550-aggre1-noc",
.data = &sm8550_aggre1_noc}, .data = &sm8550_aggre1_noc},
...@@ -2294,8 +2199,8 @@ static const struct of_device_id qnoc_of_match[] = { ...@@ -2294,8 +2199,8 @@ static const struct of_device_id qnoc_of_match[] = {
MODULE_DEVICE_TABLE(of, qnoc_of_match); MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = { static struct platform_driver qnoc_driver = {
.probe = qnoc_probe, .probe = qcom_icc_rpmh_probe,
.remove = qnoc_remove, .remove = qcom_icc_rpmh_remove,
.driver = { .driver = {
.name = "qnoc-sm8550", .name = "qnoc-sm8550",
.of_match_table = qnoc_of_match, .of_match_table = qnoc_of_match,
......
...@@ -96,14 +96,9 @@ static struct icc_node *exynos_generic_icc_xlate(struct of_phandle_args *spec, ...@@ -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) static int exynos_generic_icc_remove(struct platform_device *pdev)
{ {
struct exynos_icc_priv *priv = platform_get_drvdata(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_nodes_remove(&priv->provider);
icc_provider_del(&priv->provider);
return 0; return 0;
} }
...@@ -132,15 +127,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) ...@@ -132,15 +127,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
provider->inter_set = true; provider->inter_set = true;
provider->data = priv; provider->data = priv;
ret = icc_provider_add(provider); icc_provider_init(provider);
if (ret < 0)
return ret;
icc_node = icc_node_create(pdev->id); icc_node = icc_node_create(pdev->id);
if (IS_ERR(icc_node)) { if (IS_ERR(icc_node))
ret = PTR_ERR(icc_node); return PTR_ERR(icc_node);
goto err_prov_del;
}
priv->node = icc_node; priv->node = icc_node;
icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn", icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn",
...@@ -149,6 +140,9 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) ...@@ -149,6 +140,9 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
&priv->bus_clk_ratio)) &priv->bus_clk_ratio))
priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_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. * Register a PM QoS request for the parent (devfreq) device.
*/ */
...@@ -157,9 +151,6 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) ...@@ -157,9 +151,6 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto err_node_del; 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); icc_parent_node = exynos_icc_get_parent(bus_dev->of_node);
if (IS_ERR(icc_parent_node)) { if (IS_ERR(icc_parent_node)) {
ret = PTR_ERR(icc_parent_node); ret = PTR_ERR(icc_parent_node);
...@@ -171,14 +162,17 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) ...@@ -171,14 +162,17 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
goto err_pmqos_del; goto err_pmqos_del;
} }
ret = icc_provider_register(provider);
if (ret < 0)
goto err_pmqos_del;
return 0; return 0;
err_pmqos_del: err_pmqos_del:
dev_pm_qos_remove_request(&priv->qos_req); dev_pm_qos_remove_request(&priv->qos_req);
err_node_del: err_node_del:
icc_nodes_remove(provider); icc_nodes_remove(provider);
err_prov_del:
icc_provider_del(provider);
return ret; return ret;
} }
......
...@@ -794,16 +794,12 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) ...@@ -794,16 +794,12 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
mc->provider.aggregate = mc->soc->icc_ops->aggregate; mc->provider.aggregate = mc->soc->icc_ops->aggregate;
mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
err = icc_provider_add(&mc->provider); icc_provider_init(&mc->provider);
if (err)
return err;
/* create Memory Controller node */ /* create Memory Controller node */
node = icc_node_create(TEGRA_ICC_MC); node = icc_node_create(TEGRA_ICC_MC);
if (IS_ERR(node)) { if (IS_ERR(node))
err = PTR_ERR(node); return PTR_ERR(node);
goto del_provider;
}
node->name = "Memory Controller"; node->name = "Memory Controller";
icc_node_add(node, &mc->provider); icc_node_add(node, &mc->provider);
...@@ -830,12 +826,14 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) ...@@ -830,12 +826,14 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
goto remove_nodes; goto remove_nodes;
} }
err = icc_provider_register(&mc->provider);
if (err)
goto remove_nodes;
return 0; return 0;
remove_nodes: remove_nodes:
icc_nodes_remove(&mc->provider); icc_nodes_remove(&mc->provider);
del_provider:
icc_provider_del(&mc->provider);
return err; return err;
} }
......
...@@ -1351,15 +1351,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) ...@@ -1351,15 +1351,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended; emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider); icc_provider_init(&emc->provider);
if (err)
goto err_msg;
/* create External Memory Controller node */ /* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC); node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) { if (IS_ERR(node)) {
err = PTR_ERR(node); err = PTR_ERR(node);
goto del_provider; goto err_msg;
} }
node->name = "External Memory Controller"; node->name = "External Memory Controller";
...@@ -1380,12 +1378,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) ...@@ -1380,12 +1378,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)"; node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider); icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0; return 0;
remove_nodes: remove_nodes:
icc_nodes_remove(&emc->provider); icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg: err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err); 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) ...@@ -1021,15 +1021,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended; emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider); icc_provider_init(&emc->provider);
if (err)
goto err_msg;
/* create External Memory Controller node */ /* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC); node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) { if (IS_ERR(node)) {
err = PTR_ERR(node); err = PTR_ERR(node);
goto del_provider; goto err_msg;
} }
node->name = "External Memory Controller"; node->name = "External Memory Controller";
...@@ -1050,12 +1048,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) ...@@ -1050,12 +1048,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)"; node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider); icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0; return 0;
remove_nodes: remove_nodes:
icc_nodes_remove(&emc->provider); icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg: err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err); 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) ...@@ -1533,15 +1533,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended; emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider); icc_provider_init(&emc->provider);
if (err)
goto err_msg;
/* create External Memory Controller node */ /* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC); node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) { if (IS_ERR(node)) {
err = PTR_ERR(node); err = PTR_ERR(node);
goto del_provider; goto err_msg;
} }
node->name = "External Memory Controller"; node->name = "External Memory Controller";
...@@ -1562,12 +1560,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) ...@@ -1562,12 +1560,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
node->name = "External Memory (DRAM)"; node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider); icc_node_add(node, &emc->provider);
err = icc_provider_register(&emc->provider);
if (err)
goto remove_nodes;
return 0; return 0;
remove_nodes: remove_nodes:
icc_nodes_remove(&emc->provider); icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg: err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err); dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
......
...@@ -1231,7 +1231,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id) ...@@ -1231,7 +1231,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
"#nvmem-cell-cells", "#nvmem-cell-cells",
index, &cell_spec); index, &cell_spec);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(-ENOENT);
if (cell_spec.args_count > 1) if (cell_spec.args_count > 1)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -122,6 +122,9 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst); ...@@ -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_add(struct icc_node *node, struct icc_provider *provider);
void icc_node_del(struct icc_node *node); void icc_node_del(struct icc_node *node);
int icc_nodes_remove(struct icc_provider *provider); 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); int icc_provider_add(struct icc_provider *provider);
void icc_provider_del(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); 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) ...@@ -167,6 +170,15 @@ static inline int icc_nodes_remove(struct icc_provider *provider)
return -ENOTSUPP; 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) static inline int icc_provider_add(struct icc_provider *provider)
{ {
return -ENOTSUPP; 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