[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHUa44EG+SPt8QgMfLmEgLgGyu-EUhd8NL-9R+nbqk9Zf_bFvQ@mail.gmail.com>
Date: Wed, 28 May 2025 17:33:38 +0200
From: Jens Wiklander <jens.wiklander@...aro.org>
To: Sudeep Holla <sudeep.holla@....com>
Cc: linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
Jérôme Forissier <jerome.forissier@...aro.org>
Subject: Re: [PATCH 2/3] firmware: arm_ffa: Move memory allocation outside the
mutex locking
On Wed, May 28, 2025 at 10:50 AM Sudeep Holla <sudeep.holla@....com> wrote:
>
> 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")
> Signed-off-by: Sudeep Holla <sudeep.holla@....com>
> ---
> drivers/firmware/arm_ffa/driver.c | 48 +++++++++++++++++++--------------------
> 1 file changed, 24 insertions(+), 24 deletions(-)
Reviewed-by: Jens Wiklander <jens.wiklander@...aro.org>
Cheers,
Jens
>
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index 6f75cdf29720993b1cd95eb7d3a36d01b0fdd1de..44eecb786e67b205161e2d48602e1f1b53533360 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -1250,13 +1250,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,
> @@ -1270,18 +1269,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);
> @@ -1303,8 +1291,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);
> @@ -1335,6 +1322,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;
> @@ -1342,6 +1330,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) {
> @@ -1349,21 +1348,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.34.1
>
Powered by blists - more mailing lists