Skip to content

Commit 27e850c

Browse files
committed
firmware: arm_ffa: Move memory allocation outside the mutex locking
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: e057344 ("firmware: arm_ffa: Add interfaces to request notification callbacks") Message-Id: <[email protected]> Reviewed-by: Jens Wiklander <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent a833d31 commit 27e850c

File tree

1 file changed

+24
-24
lines changed

1 file changed

+24
-24
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,13 +1250,12 @@ notifier_hnode_get_by_type(u16 notify_id, enum notify_type type)
12501250
return NULL;
12511251
}
12521252

1253-
static int
1254-
update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb,
1255-
void *cb_data, bool is_registration, bool is_framework)
1253+
static int update_notifier_cb(struct ffa_device *dev, int notify_id,
1254+
struct notifier_cb_info *cb, bool is_framework)
12561255
{
12571256
struct notifier_cb_info *cb_info = NULL;
12581257
enum notify_type type = ffa_notify_type_get(dev->vm_id);
1259-
bool cb_found;
1258+
bool cb_found, is_registration = !!cb;
12601259

12611260
if (is_framework)
12621261
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,
12701269
return -EINVAL;
12711270

12721271
if (is_registration) {
1273-
cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL);
1274-
if (!cb_info)
1275-
return -ENOMEM;
1276-
1277-
cb_info->dev = dev;
1278-
cb_info->cb_data = cb_data;
1279-
if (is_framework)
1280-
cb_info->fwk_cb = cb;
1281-
else
1282-
cb_info->cb = cb;
1283-
1284-
hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id);
1272+
hash_add(drv_info->notifier_hash, &cb->hnode, notify_id);
12851273
} else {
12861274
hash_del(&cb_info->hnode);
12871275
kfree(cb_info);
@@ -1303,8 +1291,7 @@ static int __ffa_notify_relinquish(struct ffa_device *dev, int notify_id,
13031291

13041292
mutex_lock(&drv_info->notify_lock);
13051293

1306-
rc = update_notifier_cb(dev, notify_id, NULL, NULL, false,
1307-
is_framework);
1294+
rc = update_notifier_cb(dev, notify_id, NULL, is_framework);
13081295
if (rc) {
13091296
pr_err("Could not unregister notification callback\n");
13101297
mutex_unlock(&drv_info->notify_lock);
@@ -1335,35 +1322,48 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
13351322
{
13361323
int rc;
13371324
u32 flags = 0;
1325+
struct notifier_cb_info *cb_info = NULL;
13381326

13391327
if (ffa_notifications_disabled())
13401328
return -EOPNOTSUPP;
13411329

13421330
if (notify_id >= FFA_MAX_NOTIFICATIONS)
13431331
return -EINVAL;
13441332

1333+
cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL);
1334+
if (!cb_info)
1335+
return -ENOMEM;
1336+
1337+
cb_info->dev = dev;
1338+
cb_info->cb_data = cb_data;
1339+
if (is_framework)
1340+
cb_info->fwk_cb = cb;
1341+
else
1342+
cb_info->cb = cb;
1343+
13451344
mutex_lock(&drv_info->notify_lock);
13461345

13471346
if (!is_framework) {
13481347
if (is_per_vcpu)
13491348
flags = PER_VCPU_NOTIFICATION_FLAG;
13501349

13511350
rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags);
1352-
if (rc) {
1353-
mutex_unlock(&drv_info->notify_lock);
1354-
return rc;
1355-
}
1351+
if (rc)
1352+
goto out_unlock_free;
13561353
}
13571354

1358-
rc = update_notifier_cb(dev, notify_id, cb, cb_data, true,
1359-
is_framework);
1355+
rc = update_notifier_cb(dev, notify_id, cb_info, is_framework);
13601356
if (rc) {
13611357
pr_err("Failed to register callback for %d - %d\n",
13621358
notify_id, rc);
13631359
if (!is_framework)
13641360
ffa_notification_unbind(dev->vm_id, BIT(notify_id));
13651361
}
1362+
1363+
out_unlock_free:
13661364
mutex_unlock(&drv_info->notify_lock);
1365+
if (rc)
1366+
kfree(cb_info);
13671367

13681368
return rc;
13691369
}

0 commit comments

Comments
 (0)