[RFC PATCH 03/16] firmware: arm_scmi: Add multiple protocols registration support

Cristian Marussi
2022-02-27T20:58:22Z

Add the capability for one SCMI driver to register with the core SCMI stack
to use multiple SCMI protocols: in such a case the SCMI driver probe
function will end up being called once for each registered protocol which
have been also found as implemented on the platform.

This is especially useful in testing scenarios.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
drivers/firmware/arm_scmi/bus.c | 4 ++--
drivers/firmware/arm_scmi/common.h | 4 ++--
drivers/firmware/arm_scmi/driver.c | 24 ++++++++++++++++++++++--
3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index f6fe723ab869..e417e84249f2 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -135,7 +135,7 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
if (!driver->probe)
return -EINVAL;

- retval = scmi_protocol_device_request(driver->id_table);
+ retval = scmi_protocol_table_register(driver->id_table);
if (retval)
return retval;

@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register);
void scmi_driver_unregister(struct scmi_driver *driver)
{
driver_unregister(&driver->driver);
- scmi_protocol_device_unrequest(driver->id_table);
+ scmi_protocol_table_unregister(driver->id_table);
}
EXPORT_SYMBOL_GPL(scmi_driver_unregister);

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 4fda84bfab42..ffaf74a36b30 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -388,8 +388,8 @@ struct scmi_transport_ops {
bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);
};

-int scmi_protocol_device_request(const struct scmi_device_id *id_table);
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table);
+int scmi_protocol_table_register(const struct scmi_device_id *id_table);
+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table);
struct scmi_device *scmi_child_dev_find(struct device *parent,
int prot_id, const char *name);

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 4cb9e0ad7af5..8d356d4da0bd 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1771,7 +1771,7 @@ static void scmi_create_protocol_devices(struct device_node *np,
*
* Return: 0 on Success
*/
-int scmi_protocol_device_request(const struct scmi_device_id *id_table)
+static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
{
int ret = 0;
unsigned int id = 0;
@@ -1882,6 +1882,17 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
return ret;
}

+int scmi_protocol_table_register(const struct scmi_device_id *id_table)
+{
+ int ret = 0;
+ const struct scmi_device_id *entry;
+
+ for (entry = id_table; entry->name && ret == 0; entry++)
+ ret = scmi_protocol_device_request(entry);
+
+ return ret;
+}
+
/**
* scmi_protocol_device_unrequest - Helper to unrequest a device
*
@@ -1896,7 +1907,8 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
* that cannot be safely destroyed till the whole SCMI stack is removed.
* (unless adding further burden of refcounting.)
*/
-void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
+static void
+scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
{
struct list_head *phead;

@@ -1925,6 +1937,14 @@ void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
mutex_unlock(&scmi_requested_devices_mtx);
}

+void scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
+{
+ const struct scmi_device_id *entry;
+
+ for (entry = id_table; entry->name; entry++)
+ scmi_protocol_device_unrequest(entry);
+}
+
static int scmi_cleanup_txrx_channels(struct scmi_info *info)
{
int ret;