[PATCH v15 05/35] firmware: arm_scmi: Refactor __scmi_event_handler_get_ops helper
From: Cristian Marussi
Date: Mon Nov 09 2026 - 04:18:32 EST
Refactor the __scmi_event_handler_get_ops notification helper to simplify
its logic and make use of guards for locking.
Event handler allocation is split out of registration in a dedicated helper
so as to allow for future reuse.
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.
Reviewed-by: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>
Signed-off-by: Cristian Marussi <cristian.marussi@xxxxxxx>
---
v14 --> v15
- reworked error path in scmi_allocate_pending_event_handler
- improve commit message
---
drivers/firmware/arm_scmi/notify.c | 74 +++++++++++++++++++-----------
1 file changed, 47 insertions(+), 27 deletions(-)
diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index a30589c9b377..fa2339209a69 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -891,7 +891,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)
*
@@ -901,21 +900,33 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle,
* associated to this handler descriptor (hndl->r_evt == NULL), so the handler
* is initialized as pending.
*
- * 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;
hndl = kzalloc_obj(*hndl);
if (!hndl)
return NULL;
+
hndl->key = evt_key;
BLOCKING_INIT_NOTIFIER_HEAD(&hndl->chain);
refcount_set(&hndl->users, 1);
- /* New handlers are created pending */
+
+ 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)
+ return NULL;
+
hash_add(ni->pending_events_handlers, &hndl->hash, hndl->key);
return hndl;
@@ -1085,7 +1096,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));
@@ -1093,39 +1105,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