Skip to content

Commit

Permalink
Merge tag 'char-misc-6.3-rc3' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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
  ...
  • Loading branch information
Linus Torvalds committed Mar 19, 2023
2 parents c46a7d0 + f551592 commit ce86beb
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 322 deletions.
2 changes: 1 addition & 1 deletion drivers/firmware/xilinx/zynqmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id)
}

/* 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)
return -ENOMEM;

Expand Down
68 changes: 43 additions & 25 deletions drivers/interconnect/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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[] = {
Expand Down
20 changes: 10 additions & 10 deletions drivers/interconnect/imx/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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);

Expand Down
29 changes: 16 additions & 13 deletions drivers/interconnect/qcom/icc-rpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,28 +503,22 @@ 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;
provider->aggregate = qcom_icc_bw_aggregate;
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;

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;
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
30 changes: 19 additions & 11 deletions drivers/interconnect/qcom/icc-rpmh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
20 changes: 8 additions & 12 deletions drivers/interconnect/qcom/msm8974.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,27 +692,22 @@ 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;
provider->xlate = of_icc_xlate_onecell;
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;

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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
Loading

0 comments on commit ce86beb

Please sign in to comment.