From 546322167090286a5d81883c17a1a49b24fa10e6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Jul 2025 10:38:46 +0200 Subject: [PATCH] 6.12-stable patches added patches: firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch --- ...-add-support-for-un-registration-of-.patch | 269 ------------------ ...-move-memory-allocation-outside-the-.patch | 135 --------- ...allocation-outside-the-mutex-locking.patch | 120 ++++++++ ...-refactoring-to-prepare-for-framewor.patch | 155 ---------- ...ock-to-avoid-sleep-in-atomic-context.patch | 133 +++++++++ ...-stash-ffa_device-instead-of-notify_.patch | 110 ------- queue-6.12/series | 6 +- 7 files changed, 255 insertions(+), 673 deletions(-) delete mode 100644 queue-6.12/firmware-arm_ffa-add-support-for-un-registration-of-.patch delete mode 100644 queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-.patch create mode 100644 queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch delete mode 100644 queue-6.12/firmware-arm_ffa-refactoring-to-prepare-for-framewor.patch create mode 100644 queue-6.12/firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch delete mode 100644 queue-6.12/firmware-arm_ffa-stash-ffa_device-instead-of-notify_.patch diff --git a/queue-6.12/firmware-arm_ffa-add-support-for-un-registration-of-.patch b/queue-6.12/firmware-arm_ffa-add-support-for-un-registration-of-.patch deleted file mode 100644 index ac2870072d..0000000000 --- a/queue-6.12/firmware-arm_ffa-add-support-for-un-registration-of-.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 39d93731826e452a9266714b570c6696b185724c Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 17 Feb 2025 15:38:57 +0000 -Subject: firmware: arm_ffa: Add support for {un,}registration of framework - notifications - -From: Sudeep Holla - -[ Upstream commit c10debfe7f028c11f7a501a0f8e937c9be9e5327 ] - -Framework notifications are doorbells that are rung by the partition -managers to signal common events to an endpoint. These doorbells cannot -be rung by an endpoint directly. A partition manager can signal a -Framework notification in response to an FF-A ABI invocation by an -endpoint. - -Two additional notify_ops interface is being added for any FF-A device/ -driver to register and unregister for such a framework notifications. - -Tested-by: Viresh Kumar -Message-Id: <20250217-ffa_updates-v3-16-bd1d9de615e7@arm.com> -Signed-off-by: Sudeep Holla -Stable-dep-of: 27e850c88df0 ("firmware: arm_ffa: Move memory allocation outside the mutex locking") -Signed-off-by: Sasha Levin ---- - drivers/firmware/arm_ffa/driver.c | 113 ++++++++++++++++++++++++------ - include/linux/arm_ffa.h | 5 ++ - 2 files changed, 97 insertions(+), 21 deletions(-) - -diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c -index f0c7f417d7524..f19b142645cc5 100644 ---- a/drivers/firmware/arm_ffa/driver.c -+++ b/drivers/firmware/arm_ffa/driver.c -@@ -1079,6 +1079,7 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args) - struct notifier_cb_info { - struct hlist_node hnode; - struct ffa_device *dev; -+ ffa_fwk_notifier_cb fwk_cb; - ffa_notifier_cb cb; - void *cb_data; - }; -@@ -1142,28 +1143,61 @@ static enum notify_type ffa_notify_type_get(u16 vm_id) - return NON_SECURE_VM; - } - --/* Should be called while the notify_lock is taken */ -+/* notifier_hnode_get* should be called with notify_lock held */ - static struct notifier_cb_info * --notifier_hash_node_get(u16 notify_id, enum notify_type type) -+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 (type == ffa_notify_type_get(node->dev->vm_id)) -+ if (node->fwk_cb && vmid == node->dev->vm_id) -+ return node; -+ -+ return NULL; -+} -+ -+static struct notifier_cb_info * -+notifier_hnode_get_by_vmid_uuid(u16 notify_id, int vmid, const uuid_t *uuid) -+{ -+ struct notifier_cb_info *node; -+ -+ if (uuid_is_null(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 && -+ uuid_equal(&node->dev->uuid, uuid)) -+ return node; -+ -+ return NULL; -+} -+ -+static struct notifier_cb_info * -+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)) - return node; - - return NULL; - } - - static int --update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb, -- void *cb_data, bool is_registration) -+update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb, -+ void *cb_data, bool is_registration, bool is_framework) - { - struct notifier_cb_info *cb_info = NULL; - enum notify_type type = ffa_notify_type_get(dev->vm_id); - bool cb_found; - -- cb_info = notifier_hash_node_get(notify_id, type); -+ if (is_framework) -+ cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, dev->vm_id, -+ &dev->uuid); -+ else -+ cb_info = notifier_hnode_get_by_type(notify_id, type); -+ - cb_found = !!cb_info; - - if (!(is_registration ^ cb_found)) -@@ -1175,8 +1209,11 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb, - return -ENOMEM; - - cb_info->dev = dev; -- cb_info->cb = cb; - cb_info->cb_data = cb_data; -+ if (is_framework) -+ cb_info->fwk_cb = cb; -+ else -+ cb_info->cb = cb; - - hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id); - } else { -@@ -1187,7 +1224,8 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb, - return 0; - } - --static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) -+static int __ffa_notify_relinquish(struct ffa_device *dev, int notify_id, -+ bool is_framework) - { - int rc; - -@@ -1199,22 +1237,35 @@ static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) - - mutex_lock(&drv_info->notify_lock); - -- rc = update_notifier_cb(dev, notify_id, NULL, NULL, false); -+ rc = update_notifier_cb(dev, notify_id, NULL, NULL, false, -+ is_framework); - if (rc) { - pr_err("Could not unregister notification callback\n"); - mutex_unlock(&drv_info->notify_lock); - return rc; - } - -- rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id)); -+ if (!is_framework) -+ rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id)); - - mutex_unlock(&drv_info->notify_lock); - - return rc; - } - --static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, -- ffa_notifier_cb cb, void *cb_data, int notify_id) -+static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) -+{ -+ return __ffa_notify_relinquish(dev, notify_id, false); -+} -+ -+static int ffa_fwk_notify_relinquish(struct ffa_device *dev, int notify_id) -+{ -+ return __ffa_notify_relinquish(dev, notify_id, true); -+} -+ -+static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, -+ void *cb, void *cb_data, -+ int notify_id, bool is_framework) - { - int rc; - u32 flags = 0; -@@ -1227,26 +1278,44 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - - mutex_lock(&drv_info->notify_lock); - -- if (is_per_vcpu) -- flags = PER_VCPU_NOTIFICATION_FLAG; -+ if (!is_framework) { -+ if (is_per_vcpu) -+ flags = PER_VCPU_NOTIFICATION_FLAG; - -- rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags); -- if (rc) { -- mutex_unlock(&drv_info->notify_lock); -- return rc; -+ rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags); -+ if (rc) { -+ mutex_unlock(&drv_info->notify_lock); -+ return rc; -+ } - } - -- rc = update_notifier_cb(dev, notify_id, cb, cb_data, true); -+ rc = update_notifier_cb(dev, notify_id, cb, cb_data, true, -+ is_framework); - if (rc) { - pr_err("Failed to register callback for %d - %d\n", - notify_id, rc); -- ffa_notification_unbind(dev->vm_id, BIT(notify_id)); -+ if (!is_framework) -+ ffa_notification_unbind(dev->vm_id, BIT(notify_id)); - } - mutex_unlock(&drv_info->notify_lock); - - return rc; - } - -+static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, -+ ffa_notifier_cb cb, void *cb_data, int notify_id) -+{ -+ return __ffa_notify_request(dev, is_per_vcpu, cb, cb_data, notify_id, -+ false); -+} -+ -+static int -+ffa_fwk_notify_request(struct ffa_device *dev, ffa_fwk_notifier_cb cb, -+ void *cb_data, int notify_id) -+{ -+ return __ffa_notify_request(dev, false, cb, cb_data, notify_id, true); -+} -+ - static int ffa_notify_send(struct ffa_device *dev, int notify_id, - bool is_per_vcpu, u16 vcpu) - { -@@ -1276,7 +1345,7 @@ static void handle_notif_callbacks(u64 bitmap, enum notify_type type) - continue; - - mutex_lock(&drv_info->notify_lock); -- cb_info = notifier_hash_node_get(notify_id, type); -+ cb_info = notifier_hnode_get_by_type(notify_id, type); - mutex_unlock(&drv_info->notify_lock); - - if (cb_info && cb_info->cb) -@@ -1349,6 +1418,8 @@ static const struct ffa_notifier_ops ffa_drv_notifier_ops = { - .sched_recv_cb_unregister = ffa_sched_recv_cb_unregister, - .notify_request = ffa_notify_request, - .notify_relinquish = ffa_notify_relinquish, -+ .fwk_notify_request = ffa_fwk_notify_request, -+ .fwk_notify_relinquish = ffa_fwk_notify_relinquish, - .notify_send = ffa_notify_send, - }; - -diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h -index 74169dd0f6594..5e2530f23b793 100644 ---- a/include/linux/arm_ffa.h -+++ b/include/linux/arm_ffa.h -@@ -455,6 +455,7 @@ struct ffa_cpu_ops { - - typedef void (*ffa_sched_recv_cb)(u16 vcpu, bool is_per_vcpu, void *cb_data); - typedef void (*ffa_notifier_cb)(int notify_id, void *cb_data); -+typedef void (*ffa_fwk_notifier_cb)(int notify_id, void *cb_data, void *buf); - - struct ffa_notifier_ops { - int (*sched_recv_cb_register)(struct ffa_device *dev, -@@ -463,6 +464,10 @@ struct ffa_notifier_ops { - int (*notify_request)(struct ffa_device *dev, bool per_vcpu, - ffa_notifier_cb cb, void *cb_data, int notify_id); - int (*notify_relinquish)(struct ffa_device *dev, int notify_id); -+ int (*fwk_notify_request)(struct ffa_device *dev, -+ ffa_fwk_notifier_cb cb, void *cb_data, -+ int notify_id); -+ int (*fwk_notify_relinquish)(struct ffa_device *dev, int notify_id); - int (*notify_send)(struct ffa_device *dev, int notify_id, bool per_vcpu, - u16 vcpu); - }; --- -2.39.5 - diff --git a/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-.patch b/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-.patch deleted file mode 100644 index 322c3ebec9..0000000000 --- a/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 1a6f005f801af4f40bb68ecdce8e6c1c0df68255 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 28 May 2025 09:49:42 +0100 -Subject: firmware: arm_ffa: Move memory allocation outside the mutex locking - -From: Sudeep Holla - -[ Upstream commit 27e850c88df0e25474a8caeb2903e2e90b62c1dc ] - -The notifier callback node allocation is currently done while holding -the notify_lock mutex. While this is safe even if memory allocation may -sleep, we need to move the allocation outside the locked region in -preparation to move from using muxtes to rwlocks. - -Move the memory allocation to avoid potential sleeping in atomic context -once the locks are moved from mutex to rwlocks. - -Fixes: e0573444edbf ("firmware: arm_ffa: Add interfaces to request notification callbacks") -Message-Id: <20250528-ffa_notif_fix-v1-2-5ed7bc7f8437@arm.com> -Reviewed-by: Jens Wiklander -Signed-off-by: Sudeep Holla -Signed-off-by: Sasha Levin ---- - drivers/firmware/arm_ffa/driver.c | 48 +++++++++++++++---------------- - 1 file changed, 24 insertions(+), 24 deletions(-) - -diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c -index f19b142645cc5..33f7bdb5c86dd 100644 ---- a/drivers/firmware/arm_ffa/driver.c -+++ b/drivers/firmware/arm_ffa/driver.c -@@ -1184,13 +1184,12 @@ notifier_hnode_get_by_type(u16 notify_id, enum notify_type type) - return NULL; - } - --static int --update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb, -- void *cb_data, bool is_registration, bool is_framework) -+static int update_notifier_cb(struct ffa_device *dev, int notify_id, -+ struct notifier_cb_info *cb, bool is_framework) - { - struct notifier_cb_info *cb_info = NULL; - enum notify_type type = ffa_notify_type_get(dev->vm_id); -- bool cb_found; -+ bool cb_found, is_registration = !!cb; - - if (is_framework) - cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, dev->vm_id, -@@ -1204,18 +1203,7 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb, - return -EINVAL; - - if (is_registration) { -- cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); -- if (!cb_info) -- return -ENOMEM; -- -- cb_info->dev = dev; -- cb_info->cb_data = cb_data; -- if (is_framework) -- cb_info->fwk_cb = cb; -- else -- cb_info->cb = cb; -- -- hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id); -+ hash_add(drv_info->notifier_hash, &cb->hnode, notify_id); - } else { - hash_del(&cb_info->hnode); - kfree(cb_info); -@@ -1237,8 +1225,7 @@ static int __ffa_notify_relinquish(struct ffa_device *dev, int notify_id, - - mutex_lock(&drv_info->notify_lock); - -- rc = update_notifier_cb(dev, notify_id, NULL, NULL, false, -- is_framework); -+ rc = update_notifier_cb(dev, notify_id, NULL, is_framework); - if (rc) { - pr_err("Could not unregister notification callback\n"); - mutex_unlock(&drv_info->notify_lock); -@@ -1269,6 +1256,7 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - { - int rc; - u32 flags = 0; -+ struct notifier_cb_info *cb_info = NULL; - - if (ffa_notifications_disabled()) - return -EOPNOTSUPP; -@@ -1276,6 +1264,17 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - if (notify_id >= FFA_MAX_NOTIFICATIONS) - return -EINVAL; - -+ cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); -+ if (!cb_info) -+ return -ENOMEM; -+ -+ cb_info->dev = dev; -+ cb_info->cb_data = cb_data; -+ if (is_framework) -+ cb_info->fwk_cb = cb; -+ else -+ cb_info->cb = cb; -+ - mutex_lock(&drv_info->notify_lock); - - if (!is_framework) { -@@ -1283,21 +1282,22 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - flags = PER_VCPU_NOTIFICATION_FLAG; - - rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags); -- if (rc) { -- mutex_unlock(&drv_info->notify_lock); -- return rc; -- } -+ if (rc) -+ goto out_unlock_free; - } - -- rc = update_notifier_cb(dev, notify_id, cb, cb_data, true, -- is_framework); -+ rc = update_notifier_cb(dev, notify_id, cb_info, is_framework); - if (rc) { - pr_err("Failed to register callback for %d - %d\n", - notify_id, rc); - if (!is_framework) - ffa_notification_unbind(dev->vm_id, BIT(notify_id)); - } -+ -+out_unlock_free: - mutex_unlock(&drv_info->notify_lock); -+ if (rc) -+ kfree(cb_info); - - return rc; - } --- -2.39.5 - diff --git a/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch b/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch new file mode 100644 index 0000000000..8bcd0dca41 --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch @@ -0,0 +1,120 @@ +From 27e850c88df0e25474a8caeb2903e2e90b62c1dc Mon Sep 17 00:00:00 2001 +From: Sudeep Holla +Date: Wed, 28 May 2025 09:49:42 +0100 +Subject: firmware: arm_ffa: Move memory allocation outside the mutex locking + +From: Sudeep Holla + +commit 27e850c88df0e25474a8caeb2903e2e90b62c1dc upstream. + +The notifier callback node allocation is currently done while holding +the notify_lock mutex. While this is safe even if memory allocation may +sleep, we need to move the allocation outside the locked region in +preparation to move from using muxtes to rwlocks. + +Move the memory allocation to avoid potential sleeping in atomic context +once the locks are moved from mutex to rwlocks. + +Fixes: e0573444edbf ("firmware: arm_ffa: Add interfaces to request notification callbacks") +Message-Id: <20250528-ffa_notif_fix-v1-2-5ed7bc7f8437@arm.com> +Reviewed-by: Jens Wiklander +Signed-off-by: Sudeep Holla +Signed-off-by: Greg Kroah-Hartman +--- + +--- + drivers/firmware/arm_ffa/driver.c | 40 +++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1141,12 +1141,11 @@ notifier_hash_node_get(u16 notify_id, en + return NULL; + } + +-static int +-update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb, +- void *cb_data, bool is_registration) ++static int update_notifier_cb(int notify_id, enum notify_type type, ++ struct notifier_cb_info *cb) + { + struct notifier_cb_info *cb_info = NULL; +- bool cb_found; ++ bool cb_found, is_registration = !!cb; + + cb_info = notifier_hash_node_get(notify_id, type); + cb_found = !!cb_info; +@@ -1155,15 +1154,7 @@ update_notifier_cb(int notify_id, enum n + return -EINVAL; + + if (is_registration) { +- cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); +- if (!cb_info) +- return -ENOMEM; +- +- cb_info->type = type; +- cb_info->cb = cb; +- cb_info->cb_data = cb_data; +- +- hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id); ++ hash_add(drv_info->notifier_hash, &cb->hnode, notify_id); + } else { + hash_del(&cb_info->hnode); + kfree(cb_info); +@@ -1193,7 +1184,7 @@ static int ffa_notify_relinquish(struct + + mutex_lock(&drv_info->notify_lock); + +- rc = update_notifier_cb(notify_id, type, NULL, NULL, false); ++ rc = update_notifier_cb(notify_id, type, NULL); + if (rc) { + pr_err("Could not unregister notification callback\n"); + mutex_unlock(&drv_info->notify_lock); +@@ -1212,6 +1203,7 @@ static int ffa_notify_request(struct ffa + { + int rc; + u32 flags = 0; ++ struct notifier_cb_info *cb_info = NULL; + enum notify_type type = ffa_notify_type_get(dev->vm_id); + + if (ffa_notifications_disabled()) +@@ -1220,24 +1212,34 @@ static int ffa_notify_request(struct ffa + if (notify_id >= FFA_MAX_NOTIFICATIONS) + return -EINVAL; + ++ cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); ++ if (!cb_info) ++ return -ENOMEM; ++ ++ cb_info->type = type; ++ cb_info->cb_data = cb_data; ++ cb_info->cb = cb; ++ + mutex_lock(&drv_info->notify_lock); + + if (is_per_vcpu) + flags = PER_VCPU_NOTIFICATION_FLAG; + + rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags); +- if (rc) { +- mutex_unlock(&drv_info->notify_lock); +- return rc; +- } ++ if (rc) ++ goto out_unlock_free; + +- rc = update_notifier_cb(notify_id, type, cb, cb_data, true); ++ rc = update_notifier_cb(notify_id, type, cb_info); + if (rc) { + pr_err("Failed to register callback for %d - %d\n", + notify_id, rc); + ffa_notification_unbind(dev->vm_id, BIT(notify_id)); + } ++ ++out_unlock_free: + mutex_unlock(&drv_info->notify_lock); ++ if (rc) ++ kfree(cb_info); + + return rc; + } diff --git a/queue-6.12/firmware-arm_ffa-refactoring-to-prepare-for-framewor.patch b/queue-6.12/firmware-arm_ffa-refactoring-to-prepare-for-framewor.patch deleted file mode 100644 index bdb00d5487..0000000000 --- a/queue-6.12/firmware-arm_ffa-refactoring-to-prepare-for-framewor.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 922f199a91b30879211f73469530dfe767e784f8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 17 Feb 2025 15:38:55 +0000 -Subject: firmware: arm_ffa: Refactoring to prepare for framework notification - support - -From: Sudeep Holla - -[ Upstream commit 07b760e713255a2224cfaad62eeaae85de913bac ] - -Currently, the framework notifications are not supported at all. -handle_notif_callbacks() doesn't handle them though it is called with -framework bitmap. Make that explicit by adding checks for the same. - -Also, we need to further classify the framework notifications as Secure -Partition Manager(SPM) and NonSecure Hypervisor(NS_HYP). Extend/change -notify_type enumeration to accommodate all the 4 type and rejig the -values so that it can be reused in the bitmap enable mask macros. - -While at this, move ffa_notify_type_get() so that it can be used in -notifier_hash_node_get() in the future. - -No functional change. - -Tested-by: Viresh Kumar -Message-Id: <20250217-ffa_updates-v3-14-bd1d9de615e7@arm.com> -Signed-off-by: Sudeep Holla -Stable-dep-of: 27e850c88df0 ("firmware: arm_ffa: Move memory allocation outside the mutex locking") -Signed-off-by: Sasha Levin ---- - drivers/firmware/arm_ffa/driver.c | 57 ++++++++++++++++++------------- - 1 file changed, 34 insertions(+), 23 deletions(-) - -diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c -index c0f3b7cdb6edb..5ac6dbde31f53 100644 ---- a/drivers/firmware/arm_ffa/driver.c -+++ b/drivers/firmware/arm_ffa/driver.c -@@ -769,6 +769,13 @@ static int ffa_notification_bitmap_destroy(void) - return 0; - } - -+enum notify_type { -+ SECURE_PARTITION, -+ NON_SECURE_VM, -+ SPM_FRAMEWORK, -+ NS_HYP_FRAMEWORK, -+}; -+ - #define NOTIFICATION_LOW_MASK GENMASK(31, 0) - #define NOTIFICATION_HIGH_MASK GENMASK(63, 32) - #define NOTIFICATION_BITMAP_HIGH(x) \ -@@ -792,10 +799,17 @@ static int ffa_notification_bitmap_destroy(void) - #define MAX_IDS_32 10 - - #define PER_VCPU_NOTIFICATION_FLAG BIT(0) --#define SECURE_PARTITION_BITMAP BIT(0) --#define NON_SECURE_VM_BITMAP BIT(1) --#define SPM_FRAMEWORK_BITMAP BIT(2) --#define NS_HYP_FRAMEWORK_BITMAP BIT(3) -+#define SECURE_PARTITION_BITMAP_ENABLE BIT(SECURE_PARTITION) -+#define NON_SECURE_VM_BITMAP_ENABLE BIT(NON_SECURE_VM) -+#define SPM_FRAMEWORK_BITMAP_ENABLE BIT(SPM_FRAMEWORK) -+#define NS_HYP_FRAMEWORK_BITMAP_ENABLE BIT(NS_HYP_FRAMEWORK) -+#define FFA_BITMAP_ENABLE_MASK \ -+ (SECURE_PARTITION_BITMAP_ENABLE | SPM_FRAMEWORK_BITMAP_ENABLE) -+ -+#define FFA_SECURE_PARTITION_ID_FLAG BIT(15) -+ -+#define SPM_FRAMEWORK_BITMAP(x) NOTIFICATION_BITMAP_LOW(x) -+#define NS_HYP_FRAMEWORK_BITMAP(x) NOTIFICATION_BITMAP_HIGH(x) - - static int ffa_notification_bind_common(u16 dst_id, u64 bitmap, - u32 flags, bool is_bind) -@@ -1060,16 +1074,8 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args) - return ffa_memory_ops(FFA_MEM_LEND, args); - } - --#define FFA_SECURE_PARTITION_ID_FLAG BIT(15) -- - #define ffa_notifications_disabled() (!drv_info->notif_enabled) - --enum notify_type { -- NON_SECURE_VM, -- SECURE_PARTITION, -- FRAMEWORK, --}; -- - struct notifier_cb_info { - struct hlist_node hnode; - ffa_notifier_cb cb; -@@ -1128,6 +1134,14 @@ static int ffa_notification_unbind(u16 dst_id, u64 bitmap) - return ffa_notification_bind_common(dst_id, bitmap, 0, false); - } - -+static enum notify_type ffa_notify_type_get(u16 vm_id) -+{ -+ if (vm_id & FFA_SECURE_PARTITION_ID_FLAG) -+ return SECURE_PARTITION; -+ else -+ return NON_SECURE_VM; -+} -+ - /* Should be called while the notify_lock is taken */ - static struct notifier_cb_info * - notifier_hash_node_get(u16 notify_id, enum notify_type type) -@@ -1172,14 +1186,6 @@ update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb, - return 0; - } - --static enum notify_type ffa_notify_type_get(u16 vm_id) --{ -- if (vm_id & FFA_SECURE_PARTITION_ID_FLAG) -- return SECURE_PARTITION; -- else -- return NON_SECURE_VM; --} -- - static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) - { - int rc; -@@ -1262,6 +1268,9 @@ static void handle_notif_callbacks(u64 bitmap, enum notify_type type) - int notify_id; - struct notifier_cb_info *cb_info = NULL; - -+ if (type == SPM_FRAMEWORK || type == NS_HYP_FRAMEWORK) -+ return; -+ - for (notify_id = 0; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap; - notify_id++, bitmap >>= 1) { - if (!(bitmap & 1)) -@@ -1281,16 +1290,18 @@ static void notif_get_and_handle(void *unused) - int rc; - struct ffa_notify_bitmaps bitmaps; - -- rc = ffa_notification_get(SECURE_PARTITION_BITMAP | -- SPM_FRAMEWORK_BITMAP, &bitmaps); -+ rc = ffa_notification_get(FFA_BITMAP_ENABLE_MASK, &bitmaps); - if (rc) { - pr_err("Failed to retrieve notifications with %d!\n", rc); - return; - } - -+ handle_notif_callbacks(SPM_FRAMEWORK_BITMAP(bitmaps.arch_map), -+ SPM_FRAMEWORK); -+ handle_notif_callbacks(NS_HYP_FRAMEWORK_BITMAP(bitmaps.arch_map), -+ NS_HYP_FRAMEWORK); - handle_notif_callbacks(bitmaps.vm_map, NON_SECURE_VM); - handle_notif_callbacks(bitmaps.sp_map, SECURE_PARTITION); -- handle_notif_callbacks(bitmaps.arch_map, FRAMEWORK); - } - - static void --- -2.39.5 - diff --git a/queue-6.12/firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch b/queue-6.12/firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch new file mode 100644 index 0000000000..b013de93ab --- /dev/null +++ b/queue-6.12/firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch @@ -0,0 +1,133 @@ +From 9ca7a421229bbdfbe2e1e628cff5cfa782720a10 Mon Sep 17 00:00:00 2001 +From: Sudeep Holla +Date: Wed, 28 May 2025 09:49:43 +0100 +Subject: firmware: arm_ffa: Replace mutex with rwlock to avoid sleep in atomic context +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Sudeep Holla + +commit 9ca7a421229bbdfbe2e1e628cff5cfa782720a10 upstream. + +The current use of a mutex to protect the notifier hashtable accesses +can lead to issues in the atomic context. It results in the below +kernel warnings: + + | BUG: sleeping function called from invalid context at kernel/locking/mutex.c:258 + | in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 9, name: kworker/0:0 + | preempt_count: 1, expected: 0 + | RCU nest depth: 0, expected: 0 + | CPU: 0 UID: 0 PID: 9 Comm: kworker/0:0 Not tainted 6.14.0 #4 + | Workqueue: ffa_pcpu_irq_notification notif_pcpu_irq_work_fn + | Call trace: + | show_stack+0x18/0x24 (C) + | dump_stack_lvl+0x78/0x90 + | dump_stack+0x18/0x24 + | __might_resched+0x114/0x170 + | __might_sleep+0x48/0x98 + | mutex_lock+0x24/0x80 + | handle_notif_callbacks+0x54/0xe0 + | notif_get_and_handle+0x40/0x88 + | generic_exec_single+0x80/0xc0 + | smp_call_function_single+0xfc/0x1a0 + | notif_pcpu_irq_work_fn+0x2c/0x38 + | process_one_work+0x14c/0x2b4 + | worker_thread+0x2e4/0x3e0 + | kthread+0x13c/0x210 + | ret_from_fork+0x10/0x20 + +To address this, replace the mutex with an rwlock to protect the notifier +hashtable accesses. This ensures that read-side locking does not sleep and +multiple readers can acquire the lock concurrently, avoiding unnecessary +contention and potential deadlocks. Writer access remains exclusive, +preserving correctness. + +This change resolves warnings from lockdep about potential sleep in +atomic context. + +Cc: Jens Wiklander +Reported-by: Jérôme Forissier +Closes: https://github.com/OP-TEE/optee_os/issues/7394 +Fixes: e0573444edbf ("firmware: arm_ffa: Add interfaces to request notification callbacks") +Message-Id: <20250528-ffa_notif_fix-v1-3-5ed7bc7f8437@arm.com> +Reviewed-by: Jens Wiklander +Tested-by: Jens Wiklander +Signed-off-by: Sudeep Holla +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/arm_ffa/driver.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -110,7 +110,7 @@ struct ffa_drv_info { + struct work_struct sched_recv_irq_work; + struct xarray partition_info; + DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS)); +- struct mutex notify_lock; /* lock to protect notifier hashtable */ ++ rwlock_t notify_lock; /* lock to protect notifier hashtable */ + }; + + static struct ffa_drv_info *drv_info; +@@ -1182,18 +1182,18 @@ static int ffa_notify_relinquish(struct + if (notify_id >= FFA_MAX_NOTIFICATIONS) + return -EINVAL; + +- mutex_lock(&drv_info->notify_lock); ++ write_lock(&drv_info->notify_lock); + + rc = update_notifier_cb(notify_id, type, NULL); + if (rc) { + pr_err("Could not unregister notification callback\n"); +- mutex_unlock(&drv_info->notify_lock); ++ write_unlock(&drv_info->notify_lock); + return rc; + } + + rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id)); + +- mutex_unlock(&drv_info->notify_lock); ++ write_unlock(&drv_info->notify_lock); + + return rc; + } +@@ -1220,7 +1220,7 @@ static int ffa_notify_request(struct ffa + cb_info->cb_data = cb_data; + cb_info->cb = cb; + +- mutex_lock(&drv_info->notify_lock); ++ write_lock(&drv_info->notify_lock); + + if (is_per_vcpu) + flags = PER_VCPU_NOTIFICATION_FLAG; +@@ -1237,7 +1237,7 @@ static int ffa_notify_request(struct ffa + } + + out_unlock_free: +- mutex_unlock(&drv_info->notify_lock); ++ write_unlock(&drv_info->notify_lock); + if (rc) + kfree(cb_info); + +@@ -1269,9 +1269,9 @@ static void handle_notif_callbacks(u64 b + if (!(bitmap & 1)) + continue; + +- mutex_lock(&drv_info->notify_lock); ++ read_lock(&drv_info->notify_lock); + cb_info = notifier_hash_node_get(notify_id, type); +- mutex_unlock(&drv_info->notify_lock); ++ read_unlock(&drv_info->notify_lock); + + if (cb_info && cb_info->cb) + cb_info->cb(notify_id, cb_info->cb_data); +@@ -1721,7 +1721,7 @@ static void ffa_notifications_setup(void + goto cleanup; + + hash_init(drv_info->notifier_hash); +- mutex_init(&drv_info->notify_lock); ++ rwlock_init(&drv_info->notify_lock); + + drv_info->notif_enabled = true; + return; diff --git a/queue-6.12/firmware-arm_ffa-stash-ffa_device-instead-of-notify_.patch b/queue-6.12/firmware-arm_ffa-stash-ffa_device-instead-of-notify_.patch deleted file mode 100644 index 826f9f4d45..0000000000 --- a/queue-6.12/firmware-arm_ffa-stash-ffa_device-instead-of-notify_.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 9aaed6f314ca39a11bee06f95ae6495bf761c73b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 17 Feb 2025 15:38:56 +0000 -Subject: firmware: arm_ffa: Stash ffa_device instead of notify_type in - notifier_cb_info - -From: Sudeep Holla - -[ Upstream commit a3d73fe8ae5db389f2108a052c0a9c3c3fbc29cf ] - -Currently, we store the type of the notification in the notifier_cb_info -structure that is put into the hast list to identify if the notification -block is for the secure partition or the non secure VM. - -In order to support framework notifications to reuse the hash list and -to avoid creating one for each time, we need store the ffa_device pointer -itself as the same notification ID in framework notifications can be -registered by multiple FF-A devices. - -Tested-by: Viresh Kumar -Message-Id: <20250217-ffa_updates-v3-15-bd1d9de615e7@arm.com> -Signed-off-by: Sudeep Holla -Stable-dep-of: 27e850c88df0 ("firmware: arm_ffa: Move memory allocation outside the mutex locking") -Signed-off-by: Sasha Levin ---- - drivers/firmware/arm_ffa/driver.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c -index 5ac6dbde31f53..f0c7f417d7524 100644 ---- a/drivers/firmware/arm_ffa/driver.c -+++ b/drivers/firmware/arm_ffa/driver.c -@@ -1078,9 +1078,9 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args) - - struct notifier_cb_info { - struct hlist_node hnode; -+ struct ffa_device *dev; - ffa_notifier_cb cb; - void *cb_data; -- enum notify_type type; - }; - - static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback, -@@ -1149,17 +1149,18 @@ notifier_hash_node_get(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 (type == node->type) -+ if (type == ffa_notify_type_get(node->dev->vm_id)) - return node; - - return NULL; - } - - static int --update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb, -+update_notifier_cb(struct ffa_device *dev, int notify_id, ffa_notifier_cb cb, - void *cb_data, bool is_registration) - { - struct notifier_cb_info *cb_info = NULL; -+ enum notify_type type = ffa_notify_type_get(dev->vm_id); - bool cb_found; - - cb_info = notifier_hash_node_get(notify_id, type); -@@ -1173,7 +1174,7 @@ update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb, - if (!cb_info) - return -ENOMEM; - -- cb_info->type = type; -+ cb_info->dev = dev; - cb_info->cb = cb; - cb_info->cb_data = cb_data; - -@@ -1189,7 +1190,6 @@ update_notifier_cb(int notify_id, enum notify_type type, ffa_notifier_cb cb, - static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) - { - int rc; -- enum notify_type type = ffa_notify_type_get(dev->vm_id); - - if (ffa_notifications_disabled()) - return -EOPNOTSUPP; -@@ -1199,7 +1199,7 @@ static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id) - - mutex_lock(&drv_info->notify_lock); - -- rc = update_notifier_cb(notify_id, type, NULL, NULL, false); -+ rc = update_notifier_cb(dev, notify_id, NULL, NULL, false); - if (rc) { - pr_err("Could not unregister notification callback\n"); - mutex_unlock(&drv_info->notify_lock); -@@ -1218,7 +1218,6 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - { - int rc; - u32 flags = 0; -- enum notify_type type = ffa_notify_type_get(dev->vm_id); - - if (ffa_notifications_disabled()) - return -EOPNOTSUPP; -@@ -1237,7 +1236,7 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu, - return rc; - } - -- rc = update_notifier_cb(notify_id, type, cb, cb_data, true); -+ rc = update_notifier_cb(dev, notify_id, cb, cb_data, true); - if (rc) { - pr_err("Failed to register callback for %d - %d\n", - notify_id, rc); --- -2.39.5 - diff --git a/queue-6.12/series b/queue-6.12/series index ca914ee84d..8315111f47 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -24,10 +24,8 @@ mtk-sd-prevent-memory-corruption-from-dma-map-failure.patch mtk-sd-reset-host-mrq-on-prepare_data-error.patch drm-v3d-disable-interrupts-before-resetting-the-gpu.patch firmware-arm_ffa-fix-memory-leak-by-freeing-notifier.patch -firmware-arm_ffa-refactoring-to-prepare-for-framewor.patch -firmware-arm_ffa-stash-ffa_device-instead-of-notify_.patch -firmware-arm_ffa-add-support-for-un-registration-of-.patch -firmware-arm_ffa-move-memory-allocation-outside-the-.patch +firmware-arm_ffa-move-memory-allocation-outside-the-mutex-locking.patch +firmware-arm_ffa-replace-mutex-with-rwlock-to-avoid-sleep-in-atomic-context.patch arm64-dts-apple-t8103-fix-pcie-bcm4377-nodename.patch platform-mellanox-mlxbf-tmfifo-fix-vring_desc.len-as.patch rdma-mlx5-fix-unsafe-xarray-access-in-implicit-odp-h.patch -- 2.47.2