Loading drivers/misc/qseecom.c +67 −8 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ #include <linux/compat.h> #include "compat_qseecom.h" #include <linux/pfk.h> #include <linux/kthread.h> #define QSEECOM_DEV "qseecom" #define QSEOS_VERSION_14 0x14 Loading Loading @@ -148,6 +149,11 @@ enum qseecom_cache_ops { QSEECOM_CACHE_INVALIDATE, }; enum qseecom_listener_unregister_kthread_state { LSNR_UNREG_KT_SLEEP = 0, LSNR_UNREG_KT_WAKEUP, }; static struct class *driver_class; static dev_t qseecom_device_no; Loading Loading @@ -308,6 +314,9 @@ struct qseecom_control { struct list_head unregister_lsnr_pending_list_head; wait_queue_head_t register_lsnr_pending_wq; struct task_struct *unregister_lsnr_kthread_task; wait_queue_head_t unregister_lsnr_kthread_wq; atomic_t unregister_lsnr_kthread_state; }; struct qseecom_sec_buf_fd_info { Loading Loading @@ -1286,8 +1295,14 @@ static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc, resp.result = QSEOS_RESULT_INCOMPLETE; mutex_unlock(&listener_access_lock); mutex_lock(&app_access_lock); __qseecom_reentrancy_check_if_no_app_blocked( TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, &resp, sizeof(resp)); mutex_unlock(&app_access_lock); mutex_lock(&listener_access_lock); if (ret) { pr_err("qseecom_scm_call failed with err: %d\n", ret); ret = -EINVAL; Loading Loading @@ -1389,8 +1404,14 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data, req.listener_id = data->listener.id; resp.result = QSEOS_RESULT_INCOMPLETE; mutex_unlock(&listener_access_lock); mutex_lock(&app_access_lock); __qseecom_reentrancy_check_if_no_app_blocked( TZ_OS_DEREGISTER_LISTENER_ID); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req), &resp, sizeof(resp)); mutex_unlock(&app_access_lock); mutex_lock(&listener_access_lock); if (ret) { pr_err("scm_call() failed with err: %d (lstnr id=%d)\n", ret, data->listener.id); Loading @@ -1406,9 +1427,6 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data, goto exit; } data->abort = 1; wake_up_all(&ptr_svc->rcv_req_wq); while (atomic_read(&data->ioctl_count) > 1) { if (wait_event_freezable(data->abort_wq, atomic_read(&data->ioctl_count) <= 1)) { Loading Loading @@ -1444,6 +1462,10 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data) ptr_svc->abort = 1; wake_up_interruptible_all(&qseecom.send_resp_wq); /* stop listener thread waiting for listener request */ data->abort = 1; wake_up_all(&ptr_svc->rcv_req_wq); /* return directly if pending*/ if (ptr_svc->unregister_pending) return 0; Loading Loading @@ -1501,6 +1523,30 @@ static void __qseecom_processing_pending_lsnr_unregister(void) wake_up_interruptible(&qseecom.register_lsnr_pending_wq); } static void __wakeup_unregister_listener_kthread(void) { atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_WAKEUP); wake_up_interruptible(&qseecom.unregister_lsnr_kthread_wq); } static int __qseecom_unregister_listener_kthread_func(void *data) { while (!kthread_should_stop()) { wait_event_freezable( qseecom.unregister_lsnr_kthread_wq, atomic_read(&qseecom.unregister_lsnr_kthread_state) == LSNR_UNREG_KT_WAKEUP); pr_debug("kthread to unregister listener is called %d\n", atomic_read(&qseecom.unregister_lsnr_kthread_state)); __qseecom_processing_pending_lsnr_unregister(); atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_SLEEP); } pr_warn("kthread to unregister listener stopped\n"); return 0; } static int __qseecom_set_msm_bus_request(uint32_t mode) { int ret = 0; Loading Loading @@ -3438,7 +3484,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, } } exit: __qseecom_processing_pending_lsnr_unregister(); return ret; } Loading Loading @@ -4584,7 +4629,7 @@ int qseecom_start_app(struct qseecom_handle **handle, uint32_t fw_size, app_arch; uint32_t app_id = 0; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -4747,7 +4792,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) unsigned long flags = 0; bool found_handle = false; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -4800,7 +4845,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, struct qseecom_dev_handle *data; bool perf_enabled = false; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -7143,7 +7188,7 @@ static long qseecom_ioctl(struct file *file, cmd != QSEECOM_IOCTL_SEND_RESP_REQ && cmd != QSEECOM_IOCTL_SEND_MODFD_RESP && cmd != QSEECOM_IOCTL_SEND_MODFD_RESP_64) __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); switch (cmd) { case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: { Loading Loading @@ -8765,6 +8810,7 @@ static int qseecom_probe(struct platform_device *pdev) spin_lock_init(&qseecom.registered_kclient_list_lock); init_waitqueue_head(&qseecom.send_resp_wq); init_waitqueue_head(&qseecom.register_lsnr_pending_wq); init_waitqueue_head(&qseecom.unregister_lsnr_kthread_wq); qseecom.send_resp_flag = 0; qseecom.qsee_version = QSEEE_VERSION_00; Loading Loading @@ -8956,6 +9002,17 @@ static int qseecom_probe(struct platform_device *pdev) pr_warn("qseecom.whitelist_support = %d\n", qseecom.whitelist_support); /*create a kthread to process pending listener unregister task */ qseecom.unregister_lsnr_kthread_task = kthread_run( __qseecom_unregister_listener_kthread_func, NULL, "qseecom-unreg-lsnr"); if (IS_ERR(qseecom.unregister_lsnr_kthread_task)) { pr_err("failed to create kthread to unregister listener\n"); rc = -EINVAL; goto exit_deinit_clock; } atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_SLEEP); atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY); return 0; Loading Loading @@ -9069,6 +9126,8 @@ static int qseecom_remove(struct platform_device *pdev) __qseecom_deinit_clk(CLK_CE_DRV); } kthread_stop(qseecom.unregister_lsnr_kthread_task); cdev_del(&qseecom.cdev); device_destroy(driver_class, qseecom_device_no); Loading Loading
drivers/misc/qseecom.c +67 −8 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ #include <linux/compat.h> #include "compat_qseecom.h" #include <linux/pfk.h> #include <linux/kthread.h> #define QSEECOM_DEV "qseecom" #define QSEOS_VERSION_14 0x14 Loading Loading @@ -148,6 +149,11 @@ enum qseecom_cache_ops { QSEECOM_CACHE_INVALIDATE, }; enum qseecom_listener_unregister_kthread_state { LSNR_UNREG_KT_SLEEP = 0, LSNR_UNREG_KT_WAKEUP, }; static struct class *driver_class; static dev_t qseecom_device_no; Loading Loading @@ -308,6 +314,9 @@ struct qseecom_control { struct list_head unregister_lsnr_pending_list_head; wait_queue_head_t register_lsnr_pending_wq; struct task_struct *unregister_lsnr_kthread_task; wait_queue_head_t unregister_lsnr_kthread_wq; atomic_t unregister_lsnr_kthread_state; }; struct qseecom_sec_buf_fd_info { Loading Loading @@ -1286,8 +1295,14 @@ static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc, resp.result = QSEOS_RESULT_INCOMPLETE; mutex_unlock(&listener_access_lock); mutex_lock(&app_access_lock); __qseecom_reentrancy_check_if_no_app_blocked( TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len, &resp, sizeof(resp)); mutex_unlock(&app_access_lock); mutex_lock(&listener_access_lock); if (ret) { pr_err("qseecom_scm_call failed with err: %d\n", ret); ret = -EINVAL; Loading Loading @@ -1389,8 +1404,14 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data, req.listener_id = data->listener.id; resp.result = QSEOS_RESULT_INCOMPLETE; mutex_unlock(&listener_access_lock); mutex_lock(&app_access_lock); __qseecom_reentrancy_check_if_no_app_blocked( TZ_OS_DEREGISTER_LISTENER_ID); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req), &resp, sizeof(resp)); mutex_unlock(&app_access_lock); mutex_lock(&listener_access_lock); if (ret) { pr_err("scm_call() failed with err: %d (lstnr id=%d)\n", ret, data->listener.id); Loading @@ -1406,9 +1427,6 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data, goto exit; } data->abort = 1; wake_up_all(&ptr_svc->rcv_req_wq); while (atomic_read(&data->ioctl_count) > 1) { if (wait_event_freezable(data->abort_wq, atomic_read(&data->ioctl_count) <= 1)) { Loading Loading @@ -1444,6 +1462,10 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data) ptr_svc->abort = 1; wake_up_interruptible_all(&qseecom.send_resp_wq); /* stop listener thread waiting for listener request */ data->abort = 1; wake_up_all(&ptr_svc->rcv_req_wq); /* return directly if pending*/ if (ptr_svc->unregister_pending) return 0; Loading Loading @@ -1501,6 +1523,30 @@ static void __qseecom_processing_pending_lsnr_unregister(void) wake_up_interruptible(&qseecom.register_lsnr_pending_wq); } static void __wakeup_unregister_listener_kthread(void) { atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_WAKEUP); wake_up_interruptible(&qseecom.unregister_lsnr_kthread_wq); } static int __qseecom_unregister_listener_kthread_func(void *data) { while (!kthread_should_stop()) { wait_event_freezable( qseecom.unregister_lsnr_kthread_wq, atomic_read(&qseecom.unregister_lsnr_kthread_state) == LSNR_UNREG_KT_WAKEUP); pr_debug("kthread to unregister listener is called %d\n", atomic_read(&qseecom.unregister_lsnr_kthread_state)); __qseecom_processing_pending_lsnr_unregister(); atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_SLEEP); } pr_warn("kthread to unregister listener stopped\n"); return 0; } static int __qseecom_set_msm_bus_request(uint32_t mode) { int ret = 0; Loading Loading @@ -3438,7 +3484,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, } } exit: __qseecom_processing_pending_lsnr_unregister(); return ret; } Loading Loading @@ -4584,7 +4629,7 @@ int qseecom_start_app(struct qseecom_handle **handle, uint32_t fw_size, app_arch; uint32_t app_id = 0; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -4747,7 +4792,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) unsigned long flags = 0; bool found_handle = false; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -4800,7 +4845,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, struct qseecom_dev_handle *data; bool perf_enabled = false; __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", Loading Loading @@ -7143,7 +7188,7 @@ static long qseecom_ioctl(struct file *file, cmd != QSEECOM_IOCTL_SEND_RESP_REQ && cmd != QSEECOM_IOCTL_SEND_MODFD_RESP && cmd != QSEECOM_IOCTL_SEND_MODFD_RESP_64) __qseecom_processing_pending_lsnr_unregister(); __wakeup_unregister_listener_kthread(); switch (cmd) { case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: { Loading Loading @@ -8765,6 +8810,7 @@ static int qseecom_probe(struct platform_device *pdev) spin_lock_init(&qseecom.registered_kclient_list_lock); init_waitqueue_head(&qseecom.send_resp_wq); init_waitqueue_head(&qseecom.register_lsnr_pending_wq); init_waitqueue_head(&qseecom.unregister_lsnr_kthread_wq); qseecom.send_resp_flag = 0; qseecom.qsee_version = QSEEE_VERSION_00; Loading Loading @@ -8956,6 +9002,17 @@ static int qseecom_probe(struct platform_device *pdev) pr_warn("qseecom.whitelist_support = %d\n", qseecom.whitelist_support); /*create a kthread to process pending listener unregister task */ qseecom.unregister_lsnr_kthread_task = kthread_run( __qseecom_unregister_listener_kthread_func, NULL, "qseecom-unreg-lsnr"); if (IS_ERR(qseecom.unregister_lsnr_kthread_task)) { pr_err("failed to create kthread to unregister listener\n"); rc = -EINVAL; goto exit_deinit_clock; } atomic_set(&qseecom.unregister_lsnr_kthread_state, LSNR_UNREG_KT_SLEEP); atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY); return 0; Loading Loading @@ -9069,6 +9126,8 @@ static int qseecom_remove(struct platform_device *pdev) __qseecom_deinit_clk(CLK_CE_DRV); } kthread_stop(qseecom.unregister_lsnr_kthread_task); cdev_del(&qseecom.cdev); device_destroy(driver_class, qseecom_device_no); Loading