* [PATCH] firmware: arm_ffa: Compare notify_id when looking up notifier callbacks
@ 2026-10-20 22:09 David Cemin
0 siblings, 0 replies; only message in thread
From: David Cemin @ 2026-10-20 22:09 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linux-arm-kernel, linux-kernel, linux-tegra
The notifier callbacks are kept in a hash table keyed by notification ID,
but struct notifier_cb_info does not store the ID and none of the lookup
helpers compare it. hash_for_each_possible() walks the whole bucket, so
any two IDs that hash to the same bucket are treated as the same
registration.
With the 64-bucket table, hash_32() maps IDs 2 and 36 to the same
bucket. A driver that requests notifications sequentially therefore
fails at the 37th request:
ARM FF-A: Failed to register callback for 36 - -22
because update_notifier_cb() finds the node registered for ID 2 and
rejects the new registration as a duplicate. The same lookup is used on
the delivery path, so a notification for a colliding ID can also be
dispatched to the callback registered for the other ID.
Store the notification ID in the node and compare it in all three
lookup helpers.
This was found on an arm64 laptop whose embedded controller partition
declares 38 notifications: the EC driver failed to probe and every
EC event (AC, battery, lid, hotkeys) was lost.
Fixes: e0573444edbf ("firmware: arm_ffa: Add interfaces to request notification callbacks")
Fixes: c10debfe7f02 ("firmware: arm_ffa: Add support for {un,}registration of framework notifications")
Signed-off-by: David Cemin <dcemin@nvidia.com>
---
drivers/firmware/arm_ffa/driver.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 28abc808fd32..ae8cc3a2ba2e 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1223,6 +1223,7 @@ struct notifier_cb_info {
ffa_fwk_notifier_cb fwk_cb;
ffa_notifier_cb cb;
void *cb_data;
+ u16 notify_id;
};
static int
@@ -1302,7 +1303,8 @@ notifier_hnode_get_by_vmid(u16 notify_id, int vmid)
struct notifier_cb_info *node;
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->fwk_cb && vmid == node->dev->vm_id)
+ if (node->notify_id == notify_id && node->fwk_cb &&
+ vmid == node->dev->vm_id)
return node;
return NULL;
@@ -1317,7 +1319,8 @@ notifier_hnode_get_by_vmid_uuid(u16 notify_id, int vmid, const uuid_t *uuid)
return notifier_hnode_get_by_vmid(notify_id, vmid);
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->fwk_cb && vmid == node->dev->vm_id &&
+ if (node->notify_id == notify_id && node->fwk_cb &&
+ vmid == node->dev->vm_id &&
uuid_equal(&node->dev->uuid, uuid))
return node;
@@ -1330,7 +1333,8 @@ notifier_hnode_get_by_type(u16 notify_id, enum notify_type type)
struct notifier_cb_info *node;
hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
- if (node->cb && type == ffa_notify_type_get(node->dev->vm_id))
+ if (node->notify_id == notify_id && node->cb &&
+ type == ffa_notify_type_get(node->dev->vm_id))
return node;
return NULL;
@@ -1422,6 +1426,7 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
cb_info->dev = dev;
cb_info->cb_data = cb_data;
+ cb_info->notify_id = notify_id;
if (is_framework)
cb_info->fwk_cb = cb;
else
base-commit: 70dd4ee72eb2d5793c62e71c14e3aba78e5a4e56
--
2.55.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-20 22:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-20 22:09 [PATCH] firmware: arm_ffa: Compare notify_id when looking up notifier callbacks David Cemin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox