Jiri Slaby 221c28
From: Johan Hovold <johan+linaro@kernel.org>
Jiri Slaby 221c28
Date: Mon, 6 Mar 2023 08:56:36 +0100
Jiri Slaby 221c28
Subject: [PATCH] interconnect: qcom: rpm: fix registration race
Jiri Slaby 221c28
References: bsc#1012628
Jiri Slaby 221c28
Patch-mainline: 6.2.8
Jiri Slaby 221c28
Git-commit: 90ae93d8affc1061cd87ca8ddd9a838c7d31a158
Jiri Slaby 221c28
Jiri Slaby 221c28
commit 90ae93d8affc1061cd87ca8ddd9a838c7d31a158 upstream.
Jiri Slaby 221c28
Jiri Slaby 221c28
The current interconnect provider registration interface is inherently
Jiri Slaby 221c28
racy as nodes are not added until the after adding the provider. This
Jiri Slaby 221c28
can specifically cause racing DT lookups to fail.
Jiri Slaby 221c28
Jiri Slaby 221c28
Switch to using the new API where the provider is not registered until
Jiri Slaby 221c28
after it has been fully initialised.
Jiri Slaby 221c28
Jiri Slaby 221c28
Fixes: 62feb14ee8a3 ("interconnect: qcom: Consolidate interconnect RPM support")
Jiri Slaby 221c28
Fixes: 30c8fa3ec61a ("interconnect: qcom: Add MSM8916 interconnect provider driver")
Jiri Slaby 221c28
Cc: stable@vger.kernel.org	# 5.7
Jiri Slaby 221c28
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Jiri Slaby 221c28
Reviewed-by: Jun Nie <jun.nie@linaro.org>
Jiri Slaby 221c28
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Jiri Slaby 221c28
Link: https://lore.kernel.org/r/20230306075651.2449-9-johan+linaro@kernel.org
Jiri Slaby 221c28
Signed-off-by: Georgi Djakov <djakov@kernel.org>
Jiri Slaby 221c28
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 221c28
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 221c28
---
Jiri Slaby 221c28
 drivers/interconnect/qcom/icc-rpm.c | 24 ++++++++++++------------
Jiri Slaby 221c28
 1 file changed, 12 insertions(+), 12 deletions(-)
Jiri Slaby 221c28
Jiri Slaby 221c28
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
Jiri Slaby 221c28
index 91778cfc..4180a066 100644
Jiri Slaby 221c28
--- a/drivers/interconnect/qcom/icc-rpm.c
Jiri Slaby 221c28
+++ b/drivers/interconnect/qcom/icc-rpm.c
Jiri Slaby 221c28
@@ -503,7 +503,6 @@ int qnoc_probe(struct platform_device *pdev)
Jiri Slaby 221c28
 	}
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	provider = &qp->provider;
Jiri Slaby 221c28
-	INIT_LIST_HEAD(&provider->nodes);
Jiri Slaby 221c28
 	provider->dev = dev;
Jiri Slaby 221c28
 	provider->set = qcom_icc_set;
Jiri Slaby 221c28
 	provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
Jiri Slaby 221c28
@@ -511,12 +510,7 @@ int qnoc_probe(struct platform_device *pdev)
Jiri Slaby 221c28
 	provider->xlate_extended = qcom_icc_xlate_extended;
Jiri Slaby 221c28
 	provider->data = data;
Jiri Slaby 221c28
 
Jiri Slaby 221c28
-	ret = icc_provider_add(provider);
Jiri Slaby 221c28
-	if (ret) {
Jiri Slaby 221c28
-		dev_err(dev, "error adding interconnect provider: %d\n", ret);
Jiri Slaby 221c28
-		clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
Jiri Slaby 221c28
-		return ret;
Jiri Slaby 221c28
-	}
Jiri Slaby 221c28
+	icc_provider_init(provider);
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	for (i = 0; i < num_nodes; i++) {
Jiri Slaby 221c28
 		size_t j;
Jiri Slaby 221c28
@@ -524,7 +518,7 @@ int qnoc_probe(struct platform_device *pdev)
Jiri Slaby 221c28
 		node = icc_node_create(qnodes[i]->id);
Jiri Slaby 221c28
 		if (IS_ERR(node)) {
Jiri Slaby 221c28
 			ret = PTR_ERR(node);
Jiri Slaby 221c28
-			goto err;
Jiri Slaby 221c28
+			goto err_remove_nodes;
Jiri Slaby 221c28
 		}
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 		node->name = qnodes[i]->name;
Jiri Slaby 221c28
@@ -538,20 +532,26 @@ int qnoc_probe(struct platform_device *pdev)
Jiri Slaby 221c28
 	}
Jiri Slaby 221c28
 	data->num_nodes = num_nodes;
Jiri Slaby 221c28
 
Jiri Slaby 221c28
+	ret = icc_provider_register(provider);
Jiri Slaby 221c28
+	if (ret)
Jiri Slaby 221c28
+		goto err_remove_nodes;
Jiri Slaby 221c28
+
Jiri Slaby 221c28
 	platform_set_drvdata(pdev, qp);
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	/* Populate child NoC devices if any */
Jiri Slaby 221c28
 	if (of_get_child_count(dev->of_node) > 0) {
Jiri Slaby 221c28
 		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
Jiri Slaby 221c28
 		if (ret)
Jiri Slaby 221c28
-			goto err;
Jiri Slaby 221c28
+			goto err_deregister_provider;
Jiri Slaby 221c28
 	}
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	return 0;
Jiri Slaby 221c28
-err:
Jiri Slaby 221c28
+
Jiri Slaby 221c28
+err_deregister_provider:
Jiri Slaby 221c28
+	icc_provider_deregister(provider);
Jiri Slaby 221c28
+err_remove_nodes:
Jiri Slaby 221c28
 	icc_nodes_remove(provider);
Jiri Slaby 221c28
 	clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
Jiri Slaby 221c28
-	icc_provider_del(provider);
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	return ret;
Jiri Slaby 221c28
 }
Jiri Slaby 221c28
@@ -561,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev)
Jiri Slaby 221c28
 {
Jiri Slaby 221c28
 	struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
Jiri Slaby 221c28
 
Jiri Slaby 221c28
+	icc_provider_deregister(&qp->provider);
Jiri Slaby 221c28
 	icc_nodes_remove(&qp->provider);
Jiri Slaby 221c28
 	clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
Jiri Slaby 221c28
-	icc_provider_del(&qp->provider);
Jiri Slaby 221c28
 
Jiri Slaby 221c28
 	return 0;
Jiri Slaby 221c28
 }
Jiri Slaby 221c28
-- 
Jiri Slaby 221c28
2.35.3
Jiri Slaby 221c28