Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Sudeep Holla <sudeep.holla@kernel.org>
To: arm-scmi@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Cc: Cristian Marussi <cristian.marussi@arm.com>
Subject: [PATCH v3 11/17] firmware: arm_scmi: Clear SystemPower flag on create failure
Date: Fri, 03 Jul 2026 21:22:47 +0100	[thread overview]
Message-ID: <20260703-scmi_core_fixes-v3-11-5bae9766abfc@kernel.org> (raw)
In-Reply-To: <20260703-scmi_core_fixes-v3-0-5bae9766abfc@kernel.org>

__scmi_device_create() reserves the singleton SystemPower protocol
device by setting scmi_syspower_registered before allocating and
registering the SCMI device.

If any later step fails, the function returns NULL but leaves the flag
set. A subsequent retry, for example after probe deferral, then observes
the stale reservation and rejects creation of the SystemPower protocol
device permanently.

Route all failures after the successful reservation through a common
unwind path which clears scmi_syspower_registered again. Keep the
duplicate-device rejection path unchanged because that path did not
acquire the reservation.

The same singleton reservation can also be dropped from the final release
callback if SCMI child devices are deleted directly by the driver core
rather than through __scmi_device_destroy(). Keep the SystemPower flag
clear in the common resource helper used by destroy, register-failure and
final-release paths so all SystemPower cleanup follows the same rule.

Fixes: 2c3e674465e7 ("firmware: arm_scmi: Refactor device create/destroy helpers")
Fixes: 46edb8d1322c ("firmware: arm_scmi: provide the mandatory device release callback")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
 drivers/firmware/arm_scmi/bus.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index cbd2e6058210..11ff0b8d2c05 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -403,6 +403,9 @@ EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
 static void scmi_device_release_resources(struct scmi_device *scmi_dev)
 {
+	if (scmi_dev->protocol_id == SCMI_PROTOCOL_SYSTEM)
+		atomic_set(&scmi_syspower_registered, 0);
+
 	if (scmi_dev->id) {
 		ida_free(&scmi_bus_id, scmi_dev->id);
 		scmi_dev->id = 0;
@@ -426,9 +429,6 @@ static void __scmi_device_destroy(struct scmi_device *scmi_dev)
 		 dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
 		 scmi_dev->name);
 
-	if (scmi_dev->protocol_id == SCMI_PROTOCOL_SYSTEM)
-		atomic_set(&scmi_syspower_registered, 0);
-
 	device_del(&scmi_dev->dev);
 	scmi_device_release_resources(scmi_dev);
 	put_device(&scmi_dev->dev);
@@ -440,6 +440,7 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 {
 	int id, retval;
 	struct scmi_device *scmi_dev;
+	bool syspower = (protocol == SCMI_PROTOCOL_SYSTEM);
 
 	/*
 	 * If the same protocol/name device already exist under the same parent
@@ -455,14 +456,12 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 	}
 
 	/*
-	 * Ignore any possible subsequent failures while creating the device
-	 * since we are doomed anyway at that point; not using a mutex which
-	 * spans across this whole function to keep things simple and to avoid
-	 * to serialize all the __scmi_device_create calls across possibly
-	 * different SCMI server instances (parent)
+	 * Reserve the singleton SystemPower protocol device before
+	 * allocation and registration. This keeps creation simple without
+	 * a mutex spanning the whole function; error paths after the
+	 * reservation must drop it again.
 	 */
-	if (protocol == SCMI_PROTOCOL_SYSTEM &&
-	    atomic_cmpxchg(&scmi_syspower_registered, 0, 1)) {
+	if (syspower && atomic_cmpxchg(&scmi_syspower_registered, 0, 1)) {
 		dev_warn(parent,
 			 "SCMI SystemPower protocol device must be unique !\n");
 		return NULL;
@@ -470,19 +469,19 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 
 	scmi_dev = kzalloc_obj(*scmi_dev);
 	if (!scmi_dev)
-		return NULL;
+		goto clear_syspower;
 
 	scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
 	if (!scmi_dev->name) {
 		kfree(scmi_dev);
-		return NULL;
+		goto clear_syspower;
 	}
 
 	id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
 	if (id < 0) {
 		kfree_const(scmi_dev->name);
 		kfree(scmi_dev);
-		return NULL;
+		goto clear_syspower;
 	}
 
 	scmi_dev->id = id;
@@ -504,6 +503,9 @@ __scmi_device_create(struct device_node *np, struct device *parent,
 put_dev:
 	scmi_device_release_resources(scmi_dev);
 	put_device(&scmi_dev->dev);
+clear_syspower:
+	if (syspower)
+		atomic_set(&scmi_syspower_registered, 0);
 	return NULL;
 }
 

-- 
2.43.0



  parent reply	other threads:[~2026-07-03 20:56 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-03 20:22 [PATCH v3 00/17] firmware: arm_scmi: Fix SCMI core cleanup paths Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 01/17] firmware: arm_scmi: Fix OF node reference handling Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 02/17] firmware: arm_scmi: Fix transport device teardown lookup Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 03/17] firmware: arm_scmi: Clean up channels on setup failure Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 04/17] firmware: arm_scmi: Fix SCMI device destroy lifetimes Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 05/17] firmware: arm_scmi: Free transport channel on IDR failure Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 06/17] firmware: arm_scmi: Unregister device notifier before IDR teardown Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 07/17] firmware: arm_scmi: Unwind TX receiver mailbox setup failure Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 08/17] firmware: arm_scmi: Unwind P2A " Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 09/17] firmware: arm_scmi: Protect device request lookup with RCU Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 10/17] firmware: arm_scmi: Avoid IDR updates while cleaning channels Sudeep Holla
2026-07-03 20:22 ` Sudeep Holla [this message]
2026-07-03 20:22 ` [PATCH v3 12/17] firmware: arm_scmi: Reject out of range DT protocol IDs Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 13/17] firmware: arm_scmi: Stop channels before notification teardown Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 14/17] firmware: arm_scmi: Publish channel state before mailbox request Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 15/17] firmware: arm_scmi: Use channel ID for transport teardown Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 16/17] firmware: arm_scmi: Drop handle on protocol bind failures Sudeep Holla
2026-07-03 20:22 ` [PATCH v3 17/17] firmware: arm_scmi: Clear virtio channel lists on free Sudeep Holla

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260703-scmi_core_fixes-v3-11-5bae9766abfc@kernel.org \
    --to=sudeep.holla@kernel.org \
    --cc=arm-scmi@vger.kernel.org \
    --cc=cristian.marussi@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox