1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-12 01:20:14 +00:00

A fix in the OP-TEE driver for v6.16

Fixing a sleep in atomic context in the FF-A notification callback by
 adding a work queue to process in a non-atomic context.
 -----BEGIN PGP SIGNATURE-----
 
 iQJOBAABCgA4FiEE0qerISgy2SKkqO79Wr/6JGat8H4FAmhRB1kaHGplbnMud2lr
 bGFuZGVyQGxpbmFyby5vcmcACgkQWr/6JGat8H5+SBAArMFHmtc56NAVWO1CKbV1
 Hd9qszBXhWRYz4ahkvmC++/fOlSXKDz0YQJfKf6co32ZA8DIzgZ5QP8/YU6fJRJP
 OR+3J1qRBGD5DgdD/50fflwfE3MDLSAnSvsIxn2hhpDslnoBsg9EdUi+rxHUfSGv
 hmD6DlOvfMXGT/srFC0OxYpqKPK2wrDNxiX8b7OSd+w+QJDT5bJIO8c7ZMbyz429
 t9mdqOtBqrgEy+eosVhyPoBjzU2f7pbcOPHENu6AkopZbdBCTntGloTKs4B3HXGz
 aXYyIHpFEQIalY/3A1fkSbhEcA0NmvF33RbFcv1zz2XwxJJ18pA6Rdd2dH8nNbyb
 wXxhyzP3qAi6lBCvh985eMdejqiTcYdZLDxv3v0Xf+F5nI92TSMUuo3mRr8m0sey
 GD3dpM4RiN5WbzTXr97IlnVCDkAh/o6C6GO0chDRCjwUkgRa2ZKiBhKYs1uXUKaY
 9CpRbFMbo49RKOjlKdTcVDOk+Yw6b8U1AsCMbW3g6rAlDm1OOQG5CrTeUYc6TOX5
 bnt8BgTU8PKsjDjJbO6ch4tTIbs3leNTh+lVnTxU6762qI8UHA1bpdLJGXMNQTCn
 gbJOFYcD49o3jZeBsx0MwX/gzHiGV9+9XztGFiBZeODYToBy4f8iEI0nTUX4cUNy
 3yvUCYWf10yex5msSUBp++w=
 =EN3j
 -----END PGP SIGNATURE-----

Merge tag 'optee-fix-for-v6.16' of https://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into arm/fixes

A fix in the OP-TEE driver for v6.16

Fixing a sleep in atomic context in the FF-A notification callback by
adding a work queue to process in a non-atomic context.

* tag 'optee-fix-for-v6.16' of https://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee:
  optee: ffa: fix sleep in atomic context
This commit is contained in:
Arnd Bergmann 2025-07-03 16:26:08 +02:00
commit c6754d77bd
2 changed files with 34 additions and 9 deletions

View File

@ -728,12 +728,21 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
return true;
}
static void notif_work_fn(struct work_struct *work)
{
struct optee_ffa *optee_ffa = container_of(work, struct optee_ffa,
notif_work);
struct optee *optee = container_of(optee_ffa, struct optee, ffa);
optee_do_bottom_half(optee->ctx);
}
static void notif_callback(int notify_id, void *cb_data)
{
struct optee *optee = cb_data;
if (notify_id == optee->ffa.bottom_half_value)
optee_do_bottom_half(optee->ctx);
queue_work(optee->ffa.notif_wq, &optee->ffa.notif_work);
else
optee_notif_send(optee, notify_id);
}
@ -817,9 +826,11 @@ static void optee_ffa_remove(struct ffa_device *ffa_dev)
struct optee *optee = ffa_dev_get_drvdata(ffa_dev);
u32 bottom_half_id = optee->ffa.bottom_half_value;
if (bottom_half_id != U32_MAX)
if (bottom_half_id != U32_MAX) {
ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev,
bottom_half_id);
destroy_workqueue(optee->ffa.notif_wq);
}
optee_remove_common(optee);
mutex_destroy(&optee->ffa.mutex);
@ -835,6 +846,13 @@ static int optee_ffa_async_notif_init(struct ffa_device *ffa_dev,
u32 notif_id = 0;
int rc;
INIT_WORK(&optee->ffa.notif_work, notif_work_fn);
optee->ffa.notif_wq = create_workqueue("optee_notification");
if (!optee->ffa.notif_wq) {
rc = -EINVAL;
goto err;
}
while (true) {
rc = ffa_dev->ops->notifier_ops->notify_request(ffa_dev,
is_per_vcpu,
@ -851,19 +869,24 @@ static int optee_ffa_async_notif_init(struct ffa_device *ffa_dev,
* notifications in that case.
*/
if (rc != -EACCES)
return rc;
goto err_wq;
notif_id++;
if (notif_id >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE)
return rc;
goto err_wq;
}
optee->ffa.bottom_half_value = notif_id;
rc = enable_async_notif(optee);
if (rc < 0) {
ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev,
notif_id);
optee->ffa.bottom_half_value = U32_MAX;
}
if (rc < 0)
goto err_rel;
return 0;
err_rel:
ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, notif_id);
err_wq:
destroy_workqueue(optee->ffa.notif_wq);
err:
optee->ffa.bottom_half_value = U32_MAX;
return rc;
}

View File

@ -165,6 +165,8 @@ struct optee_ffa {
/* Serializes access to @global_ids */
struct mutex mutex;
struct rhashtable global_ids;
struct workqueue_struct *notif_wq;
struct work_struct notif_work;
};
struct optee;