diff mbox series

[v2,1/4] firmware: arm_scmi: Support only one single SystemPower device

Message ID 20220704101933.2981635-2-cristian.marussi@arm.com (mailing list archive)
State New, archived
Headers show
Series Introduce SCMI System Power Control driver | expand

Commit Message

Cristian Marussi July 4, 2022, 10:19 a.m. UTC
In order to minimize SCMI platform fw-side complexity, only one single SCMI
platform should be in charge of SCMI SystemPower protocol communications
with the OSPM: enforce the existence of one single unique device associated
with SystemPower protocol across any possible number of SCMI platforms, and
warn if a system tries to register different SystemPower devices from
multiple platforms.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
v1 --> v2
- move single device checks from bus to driver
---
 drivers/firmware/arm_scmi/bus.c    |  1 +
 drivers/firmware/arm_scmi/driver.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)
diff mbox series

Patch

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index f6fe723ab869..8960fb5277db 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -201,6 +201,7 @@  scmi_device_create(struct device_node *np, struct device *parent, int protocol,
 		goto put_dev;
 
 	return scmi_dev;
+
 put_dev:
 	kfree_const(scmi_dev->name);
 	put_device(&scmi_dev->dev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 00b7f2aff4ec..48392a8a8dcd 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -61,6 +61,11 @@  static atomic_t transfer_last_id;
 static DEFINE_IDR(scmi_requested_devices);
 static DEFINE_MUTEX(scmi_requested_devices_mtx);
 
+/* Track globally the creation of SCMI SystemPower related devices */
+static bool scmi_syspower_registered;
+/* Protect access to scmi_syspower_registered */
+static DEFINE_MUTEX(scmi_syspower_mtx);
+
 struct scmi_requested_dev {
 	const struct scmi_device_id *id_table;
 	struct list_head node;
@@ -2014,21 +2019,39 @@  scmi_get_protocol_device(struct device_node *np, struct scmi_info *info,
 	if (sdev)
 		return sdev;
 
+	mutex_lock(&scmi_syspower_mtx);
+	if (prot_id == SCMI_PROTOCOL_SYSTEM && scmi_syspower_registered) {
+		dev_warn(info->dev,
+			 "SCMI SystemPower protocol device must be unique !\n");
+		mutex_unlock(&scmi_syspower_mtx);
+
+		return NULL;
+	}
+
 	pr_debug("Creating SCMI device (%s) for protocol %x\n", name, prot_id);
 
 	sdev = scmi_device_create(np, info->dev, prot_id, name);
 	if (!sdev) {
 		dev_err(info->dev, "failed to create %d protocol device\n",
 			prot_id);
+		mutex_unlock(&scmi_syspower_mtx);
+
 		return NULL;
 	}
 
 	if (scmi_txrx_setup(info, &sdev->dev, prot_id)) {
 		dev_err(&sdev->dev, "failed to setup transport\n");
 		scmi_device_destroy(sdev);
+		mutex_unlock(&scmi_syspower_mtx);
+
 		return NULL;
 	}
 
+	if (prot_id == SCMI_PROTOCOL_SYSTEM)
+		scmi_syspower_registered = true;
+
+	mutex_unlock(&scmi_syspower_mtx);
+
 	return sdev;
 }