[PATCH v14 03/32] firmware: arm_scmi: Refactor __scmi_event_handler_get_ops helper

From: Cristian Marussi

Date: Fri Oct 16 2026 - 14:57:54 EST


Refactor the __scmi_event_handler_get_ops notification helper to simplify
its logic and make use of guards for locking.

Mostly no functional change, in the sense that while the functionality
remained the same, a richer set of errors is returned where before was
always a -EINVAL.

Signed-off-by: Cristian Marussi <cristian.marussi@xxxxxxx>
---
drivers/firmware/arm_scmi/notify.c | 73 +++++++++++++++++++-----------
1 file changed, 46 insertions(+), 27 deletions(-)

diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index 7d1bb424a723..2bc2e03df639 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -890,7 +890,6 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle,

/**
* scmi_allocate_event_handler() - Allocate Event handler
- * @ni: A reference to the notification instance to use
* @evt_key: 32bit key uniquely bind to the event identified by the tuple
* (proto_id, evt_id, src_id)
*
@@ -903,8 +902,7 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle,
* Context: Assumes to be called with @pending_mtx already acquired.
* Return: the freshly allocated structure on Success
*/
-static struct scmi_event_handler *
-scmi_allocate_event_handler(struct scmi_notify_instance *ni, u32 evt_key)
+static struct scmi_event_handler *scmi_allocate_event_handler(u32 evt_key)
{
struct scmi_event_handler *hndl;

@@ -914,8 +912,20 @@ scmi_allocate_event_handler(struct scmi_notify_instance *ni, u32 evt_key)
hndl->key = evt_key;
BLOCKING_INIT_NOTIFIER_HEAD(&hndl->chain);
refcount_set(&hndl->users, 1);
- /* New handlers are created pending */
- hash_add(ni->pending_events_handlers, &hndl->hash, hndl->key);
+
+ return hndl;
+}
+
+static struct scmi_event_handler *
+scmi_allocate_pending_event_handler(struct scmi_notify_instance *ni,
+ u32 evt_key)
+{
+ struct scmi_event_handler *hndl;
+
+ lockdep_assert_held(&ni->pending_mtx);
+ hndl = scmi_allocate_event_handler(evt_key);
+ if (hndl)
+ hash_add(ni->pending_events_handlers, &hndl->hash, hndl->key);

return hndl;
}
@@ -1084,7 +1094,8 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
u32 evt_key, bool create)
{
struct scmi_registered_event *r_evt;
- struct scmi_event_handler *hndl = NULL;
+ struct scmi_event_handler *hndl;
+ int ret;

r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key),
KEY_XTRACT_EVT_ID(evt_key));
@@ -1092,39 +1103,47 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
if (r_evt && r_evt->not_supported_by_platform)
return ERR_PTR(-EOPNOTSUPP);

- mutex_lock(&ni->pending_mtx);
+ guard(mutex)(&ni->pending_mtx);
/* Search registered events at first ... if possible at all */
if (r_evt) {
- mutex_lock(&r_evt->proto->registered_mtx);
+ guard(mutex)(&r_evt->proto->registered_mtx);
hndl = KEY_FIND(r_evt->proto->registered_events_handlers,
hndl, evt_key);
- if (hndl)
+ if (hndl) {
refcount_inc(&hndl->users);
- mutex_unlock(&r_evt->proto->registered_mtx);
+ return hndl;
+ }
}

/* ...then amongst pending. */
- if (!hndl) {
- hndl = KEY_FIND(ni->pending_events_handlers, hndl, evt_key);
- if (hndl)
- refcount_inc(&hndl->users);
+ hndl = KEY_FIND(ni->pending_events_handlers, hndl, evt_key);
+ if (hndl) {
+ refcount_inc(&hndl->users);
+ return hndl;
}

- /* Create if still not found and required */
- if (!hndl && create) {
- hndl = scmi_allocate_event_handler(ni, evt_key);
- if (hndl && scmi_register_event_handler(ni, hndl)) {
- dev_dbg(ni->handle->dev,
- "purging UNKNOWN handler - key:%X\n",
- hndl->key);
- /* this hndl can be only a pending one */
- scmi_put_handler_unlocked(ni, hndl);
- hndl = ERR_PTR(-EINVAL);
- }
+ if (!create)
+ return ERR_PTR(-ENODEV);
+
+ /*
+ * Create if still not found and required, new handlers are
+ * created pending and transitioned to registered when bound to
+ * an event.
+ */
+ hndl = scmi_allocate_pending_event_handler(ni, evt_key);
+ if (!hndl)
+ return ERR_PTR(-ENOMEM);
+
+ ret = scmi_register_event_handler(ni, hndl);
+ if (ret) {
+ dev_dbg(ni->handle->dev,
+ "purging UNKNOWN handler - key:%X\n", hndl->key);
+ /* this hndl can be only a pending one */
+ scmi_put_handler_unlocked(ni, hndl);
+ return ERR_PTR(ret);
}
- mutex_unlock(&ni->pending_mtx);

- return hndl ?: ERR_PTR(-ENODEV);
+ return hndl;
}

static struct scmi_event_handler *
--
2.54.0