Skip to content

Commit 3140551

Browse files
sudeep-hollagregkh
authored andcommitted
firmware: arm_ffa: Replace mutex with rwlock to avoid sleep in atomic context
commit 9ca7a42 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 <[email protected]> Reported-by: Jérôme Forissier <[email protected]> Closes: OP-TEE/optee_os#7394 Fixes: e057344 ("firmware: arm_ffa: Add interfaces to request notification callbacks") Message-Id: <[email protected]> Reviewed-by: Jens Wiklander <[email protected]> Tested-by: Jens Wiklander <[email protected]> Signed-off-by: Sudeep Holla <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2c07fd0 commit 3140551

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ struct ffa_drv_info {
110110
struct work_struct sched_recv_irq_work;
111111
struct xarray partition_info;
112112
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
113-
struct mutex notify_lock; /* lock to protect notifier hashtable */
113+
rwlock_t notify_lock; /* lock to protect notifier hashtable */
114114
};
115115

116116
static struct ffa_drv_info *drv_info;
@@ -1182,18 +1182,18 @@ static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
11821182
if (notify_id >= FFA_MAX_NOTIFICATIONS)
11831183
return -EINVAL;
11841184

1185-
mutex_lock(&drv_info->notify_lock);
1185+
write_lock(&drv_info->notify_lock);
11861186

11871187
rc = update_notifier_cb(notify_id, type, NULL);
11881188
if (rc) {
11891189
pr_err("Could not unregister notification callback\n");
1190-
mutex_unlock(&drv_info->notify_lock);
1190+
write_unlock(&drv_info->notify_lock);
11911191
return rc;
11921192
}
11931193

11941194
rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id));
11951195

1196-
mutex_unlock(&drv_info->notify_lock);
1196+
write_unlock(&drv_info->notify_lock);
11971197

11981198
return rc;
11991199
}
@@ -1220,7 +1220,7 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
12201220
cb_info->cb_data = cb_data;
12211221
cb_info->cb = cb;
12221222

1223-
mutex_lock(&drv_info->notify_lock);
1223+
write_lock(&drv_info->notify_lock);
12241224

12251225
if (is_per_vcpu)
12261226
flags = PER_VCPU_NOTIFICATION_FLAG;
@@ -1237,7 +1237,7 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
12371237
}
12381238

12391239
out_unlock_free:
1240-
mutex_unlock(&drv_info->notify_lock);
1240+
write_unlock(&drv_info->notify_lock);
12411241
if (rc)
12421242
kfree(cb_info);
12431243

@@ -1269,9 +1269,9 @@ static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
12691269
if (!(bitmap & 1))
12701270
continue;
12711271

1272-
mutex_lock(&drv_info->notify_lock);
1272+
read_lock(&drv_info->notify_lock);
12731273
cb_info = notifier_hash_node_get(notify_id, type);
1274-
mutex_unlock(&drv_info->notify_lock);
1274+
read_unlock(&drv_info->notify_lock);
12751275

12761276
if (cb_info && cb_info->cb)
12771277
cb_info->cb(notify_id, cb_info->cb_data);
@@ -1721,7 +1721,7 @@ static void ffa_notifications_setup(void)
17211721
goto cleanup;
17221722

17231723
hash_init(drv_info->notifier_hash);
1724-
mutex_init(&drv_info->notify_lock);
1724+
rwlock_init(&drv_info->notify_lock);
17251725

17261726
drv_info->notif_enabled = true;
17271727
return;

0 commit comments

Comments
 (0)