Skip to content

Commit ce86beb

Browse files
committed
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 ...
2 parents c46a7d0 + f551592 commit ce86beb

File tree

17 files changed

+160
-322
lines changed

17 files changed

+160
-322
lines changed

drivers/firmware/xilinx/zynqmp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id)
206206
}
207207

208208
/* Add new entry if not present */
209-
feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
209+
feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
210210
if (!feature_data)
211211
return -ENOMEM;
212212

drivers/interconnect/core.c

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,10 @@ void icc_node_destroy(int id)
850850

851851
mutex_unlock(&icc_lock);
852852

853+
if (!node)
854+
return;
855+
856+
kfree(node->links);
853857
kfree(node);
854858
}
855859
EXPORT_SYMBOL_GPL(icc_node_destroy);
@@ -1029,54 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider)
10291033
EXPORT_SYMBOL_GPL(icc_nodes_remove);
10301034

10311035
/**
1032-
* icc_provider_add() - add a new interconnect provider
1033-
* @provider: the interconnect provider that will be added into topology
1036+
* icc_provider_init() - initialize a new interconnect provider
1037+
* @provider: the interconnect provider to initialize
1038+
*
1039+
* Must be called before adding nodes to the provider.
1040+
*/
1041+
void icc_provider_init(struct icc_provider *provider)
1042+
{
1043+
WARN_ON(!provider->set);
1044+
1045+
INIT_LIST_HEAD(&provider->nodes);
1046+
}
1047+
EXPORT_SYMBOL_GPL(icc_provider_init);
1048+
1049+
/**
1050+
* icc_provider_register() - register a new interconnect provider
1051+
* @provider: the interconnect provider to register
10341052
*
10351053
* Return: 0 on success, or an error code otherwise
10361054
*/
1037-
int icc_provider_add(struct icc_provider *provider)
1055+
int icc_provider_register(struct icc_provider *provider)
10381056
{
1039-
if (WARN_ON(!provider->set))
1040-
return -EINVAL;
10411057
if (WARN_ON(!provider->xlate && !provider->xlate_extended))
10421058
return -EINVAL;
10431059

10441060
mutex_lock(&icc_lock);
1045-
1046-
INIT_LIST_HEAD(&provider->nodes);
10471061
list_add_tail(&provider->provider_list, &icc_providers);
1048-
10491062
mutex_unlock(&icc_lock);
10501063

1051-
dev_dbg(provider->dev, "interconnect provider added to topology\n");
1064+
dev_dbg(provider->dev, "interconnect provider registered\n");
10521065

10531066
return 0;
10541067
}
1055-
EXPORT_SYMBOL_GPL(icc_provider_add);
1068+
EXPORT_SYMBOL_GPL(icc_provider_register);
10561069

10571070
/**
1058-
* icc_provider_del() - delete previously added interconnect provider
1059-
* @provider: the interconnect provider that will be removed from topology
1071+
* icc_provider_deregister() - deregister an interconnect provider
1072+
* @provider: the interconnect provider to deregister
10601073
*/
1061-
void icc_provider_del(struct icc_provider *provider)
1074+
void icc_provider_deregister(struct icc_provider *provider)
10621075
{
10631076
mutex_lock(&icc_lock);
1064-
if (provider->users) {
1065-
pr_warn("interconnect provider still has %d users\n",
1066-
provider->users);
1067-
mutex_unlock(&icc_lock);
1068-
return;
1069-
}
1070-
1071-
if (!list_empty(&provider->nodes)) {
1072-
pr_warn("interconnect provider still has nodes\n");
1073-
mutex_unlock(&icc_lock);
1074-
return;
1075-
}
1077+
WARN_ON(provider->users);
10761078

10771079
list_del(&provider->provider_list);
10781080
mutex_unlock(&icc_lock);
10791081
}
1082+
EXPORT_SYMBOL_GPL(icc_provider_deregister);
1083+
1084+
int icc_provider_add(struct icc_provider *provider)
1085+
{
1086+
icc_provider_init(provider);
1087+
1088+
return icc_provider_register(provider);
1089+
}
1090+
EXPORT_SYMBOL_GPL(icc_provider_add);
1091+
1092+
void icc_provider_del(struct icc_provider *provider)
1093+
{
1094+
WARN_ON(!list_empty(&provider->nodes));
1095+
1096+
icc_provider_deregister(provider);
1097+
}
10801098
EXPORT_SYMBOL_GPL(icc_provider_del);
10811099

10821100
static const struct of_device_id __maybe_unused ignore_list[] = {

drivers/interconnect/imx/imx.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev,
295295
provider->xlate = of_icc_xlate_onecell;
296296
provider->data = data;
297297
provider->dev = dev->parent;
298+
299+
icc_provider_init(provider);
300+
298301
platform_set_drvdata(pdev, imx_provider);
299302

300303
if (settings) {
@@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev,
306309
}
307310
}
308311

309-
ret = icc_provider_add(provider);
310-
if (ret) {
311-
dev_err(dev, "error adding interconnect provider: %d\n", ret);
312+
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
313+
if (ret)
312314
return ret;
313-
}
314315

315-
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
316+
ret = icc_provider_register(provider);
316317
if (ret)
317-
goto provider_del;
318+
goto err_unregister_nodes;
318319

319320
return 0;
320321

321-
provider_del:
322-
icc_provider_del(provider);
322+
err_unregister_nodes:
323+
imx_icc_unregister_nodes(&imx_provider->provider);
323324
return ret;
324325
}
325326
EXPORT_SYMBOL_GPL(imx_icc_register);
@@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev)
328329
{
329330
struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
330331

332+
icc_provider_deregister(&imx_provider->provider);
331333
imx_icc_unregister_nodes(&imx_provider->provider);
332-
333-
icc_provider_del(&imx_provider->provider);
334334
}
335335
EXPORT_SYMBOL_GPL(imx_icc_unregister);
336336

drivers/interconnect/qcom/icc-rpm.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -503,28 +503,22 @@ int qnoc_probe(struct platform_device *pdev)
503503
}
504504

505505
provider = &qp->provider;
506-
INIT_LIST_HEAD(&provider->nodes);
507506
provider->dev = dev;
508507
provider->set = qcom_icc_set;
509508
provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
510509
provider->aggregate = qcom_icc_bw_aggregate;
511510
provider->xlate_extended = qcom_icc_xlate_extended;
512511
provider->data = data;
513512

514-
ret = icc_provider_add(provider);
515-
if (ret) {
516-
dev_err(dev, "error adding interconnect provider: %d\n", ret);
517-
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
518-
return ret;
519-
}
513+
icc_provider_init(provider);
520514

521515
for (i = 0; i < num_nodes; i++) {
522516
size_t j;
523517

524518
node = icc_node_create(qnodes[i]->id);
525519
if (IS_ERR(node)) {
526520
ret = PTR_ERR(node);
527-
goto err;
521+
goto err_remove_nodes;
528522
}
529523

530524
node->name = qnodes[i]->name;
@@ -538,17 +532,26 @@ int qnoc_probe(struct platform_device *pdev)
538532
}
539533
data->num_nodes = num_nodes;
540534

535+
ret = icc_provider_register(provider);
536+
if (ret)
537+
goto err_remove_nodes;
538+
541539
platform_set_drvdata(pdev, qp);
542540

543541
/* Populate child NoC devices if any */
544-
if (of_get_child_count(dev->of_node) > 0)
545-
return of_platform_populate(dev->of_node, NULL, NULL, dev);
542+
if (of_get_child_count(dev->of_node) > 0) {
543+
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
544+
if (ret)
545+
goto err_deregister_provider;
546+
}
546547

547548
return 0;
548-
err:
549+
550+
err_deregister_provider:
551+
icc_provider_deregister(provider);
552+
err_remove_nodes:
549553
icc_nodes_remove(provider);
550554
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
551-
icc_provider_del(provider);
552555

553556
return ret;
554557
}
@@ -558,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev)
558561
{
559562
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
560563

564+
icc_provider_deregister(&qp->provider);
561565
icc_nodes_remove(&qp->provider);
562566
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
563-
icc_provider_del(&qp->provider);
564567

565568
return 0;
566569
}

drivers/interconnect/qcom/icc-rpmh.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
192192
provider->pre_aggregate = qcom_icc_pre_aggregate;
193193
provider->aggregate = qcom_icc_aggregate;
194194
provider->xlate_extended = qcom_icc_xlate_extended;
195-
INIT_LIST_HEAD(&provider->nodes);
196195
provider->data = data;
197196

197+
icc_provider_init(provider);
198+
198199
qp->dev = dev;
199200
qp->bcms = desc->bcms;
200201
qp->num_bcms = desc->num_bcms;
@@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
203204
if (IS_ERR(qp->voter))
204205
return PTR_ERR(qp->voter);
205206

206-
ret = icc_provider_add(provider);
207-
if (ret)
208-
return ret;
209-
210207
for (i = 0; i < qp->num_bcms; i++)
211208
qcom_icc_bcm_init(qp->bcms[i], dev);
212209

@@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
218215
node = icc_node_create(qn->id);
219216
if (IS_ERR(node)) {
220217
ret = PTR_ERR(node);
221-
goto err;
218+
goto err_remove_nodes;
222219
}
223220

224221
node->name = qn->name;
@@ -232,16 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
232229
}
233230

234231
data->num_nodes = num_nodes;
232+
233+
ret = icc_provider_register(provider);
234+
if (ret)
235+
goto err_remove_nodes;
236+
235237
platform_set_drvdata(pdev, qp);
236238

237239
/* Populate child NoC devices if any */
238-
if (of_get_child_count(dev->of_node) > 0)
239-
return of_platform_populate(dev->of_node, NULL, NULL, dev);
240+
if (of_get_child_count(dev->of_node) > 0) {
241+
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
242+
if (ret)
243+
goto err_deregister_provider;
244+
}
240245

241246
return 0;
242-
err:
247+
248+
err_deregister_provider:
249+
icc_provider_deregister(provider);
250+
err_remove_nodes:
243251
icc_nodes_remove(provider);
244-
icc_provider_del(provider);
252+
245253
return ret;
246254
}
247255
EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe);
@@ -250,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
250258
{
251259
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
252260

261+
icc_provider_deregister(&qp->provider);
253262
icc_nodes_remove(&qp->provider);
254-
icc_provider_del(&qp->provider);
255263

256264
return 0;
257265
}

drivers/interconnect/qcom/msm8974.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -692,27 +692,22 @@ static int msm8974_icc_probe(struct platform_device *pdev)
692692
return ret;
693693

694694
provider = &qp->provider;
695-
INIT_LIST_HEAD(&provider->nodes);
696695
provider->dev = dev;
697696
provider->set = msm8974_icc_set;
698697
provider->aggregate = icc_std_aggregate;
699698
provider->xlate = of_icc_xlate_onecell;
700699
provider->data = data;
701700
provider->get_bw = msm8974_get_bw;
702701

703-
ret = icc_provider_add(provider);
704-
if (ret) {
705-
dev_err(dev, "error adding interconnect provider: %d\n", ret);
706-
goto err_disable_clks;
707-
}
702+
icc_provider_init(provider);
708703

709704
for (i = 0; i < num_nodes; i++) {
710705
size_t j;
711706

712707
node = icc_node_create(qnodes[i]->id);
713708
if (IS_ERR(node)) {
714709
ret = PTR_ERR(node);
715-
goto err_del_icc;
710+
goto err_remove_nodes;
716711
}
717712

718713
node->name = qnodes[i]->name;
@@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev)
729724
}
730725
data->num_nodes = num_nodes;
731726

727+
ret = icc_provider_register(provider);
728+
if (ret)
729+
goto err_remove_nodes;
730+
732731
platform_set_drvdata(pdev, qp);
733732

734733
return 0;
735734

736-
err_del_icc:
735+
err_remove_nodes:
737736
icc_nodes_remove(provider);
738-
icc_provider_del(provider);
739-
740-
err_disable_clks:
741737
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
742738

743739
return ret;
@@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
747743
{
748744
struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
749745

746+
icc_provider_deregister(&qp->provider);
750747
icc_nodes_remove(&qp->provider);
751748
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
752-
icc_provider_del(&qp->provider);
753749

754750
return 0;
755751
}

0 commit comments

Comments
 (0)