Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+34 -9
+32 -9
drivers/tee/optee/ffa_abi.c
··· 728 728 return true; 729 729 } 730 730 731 + static void notif_work_fn(struct work_struct *work) 732 + { 733 + struct optee_ffa *optee_ffa = container_of(work, struct optee_ffa, 734 + notif_work); 735 + struct optee *optee = container_of(optee_ffa, struct optee, ffa); 736 + 737 + optee_do_bottom_half(optee->ctx); 738 + } 739 + 731 740 static void notif_callback(int notify_id, void *cb_data) 732 741 { 733 742 struct optee *optee = cb_data; 734 743 735 744 if (notify_id == optee->ffa.bottom_half_value) 736 - optee_do_bottom_half(optee->ctx); 745 + queue_work(optee->ffa.notif_wq, &optee->ffa.notif_work); 737 746 else 738 747 optee_notif_send(optee, notify_id); 739 748 } ··· 826 817 struct optee *optee = ffa_dev_get_drvdata(ffa_dev); 827 818 u32 bottom_half_id = optee->ffa.bottom_half_value; 828 819 829 - if (bottom_half_id != U32_MAX) 820 + if (bottom_half_id != U32_MAX) { 830 821 ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, 831 822 bottom_half_id); 823 + destroy_workqueue(optee->ffa.notif_wq); 824 + } 832 825 optee_remove_common(optee); 833 826 834 827 mutex_destroy(&optee->ffa.mutex); ··· 845 834 bool is_per_vcpu = false; 846 835 u32 notif_id = 0; 847 836 int rc; 837 + 838 + INIT_WORK(&optee->ffa.notif_work, notif_work_fn); 839 + optee->ffa.notif_wq = create_workqueue("optee_notification"); 840 + if (!optee->ffa.notif_wq) { 841 + rc = -EINVAL; 842 + goto err; 843 + } 848 844 849 845 while (true) { 850 846 rc = ffa_dev->ops->notifier_ops->notify_request(ffa_dev, ··· 869 851 * notifications in that case. 870 852 */ 871 853 if (rc != -EACCES) 872 - return rc; 854 + goto err_wq; 873 855 notif_id++; 874 856 if (notif_id >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE) 875 - return rc; 857 + goto err_wq; 876 858 } 877 859 optee->ffa.bottom_half_value = notif_id; 878 860 879 861 rc = enable_async_notif(optee); 880 - if (rc < 0) { 881 - ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, 882 - notif_id); 883 - optee->ffa.bottom_half_value = U32_MAX; 884 - } 862 + if (rc < 0) 863 + goto err_rel; 864 + 865 + return 0; 866 + err_rel: 867 + ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, notif_id); 868 + err_wq: 869 + destroy_workqueue(optee->ffa.notif_wq); 870 + err: 871 + optee->ffa.bottom_half_value = U32_MAX; 885 872 886 873 return rc; 887 874 }
+2
drivers/tee/optee/optee_private.h
··· 165 165 /* Serializes access to @global_ids */ 166 166 struct mutex mutex; 167 167 struct rhashtable global_ids; 168 + struct workqueue_struct *notif_wq; 169 + struct work_struct notif_work; 168 170 }; 169 171 170 172 struct optee;