Loading drivers/misc/qseecom.c +67 −8 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ #include <linux/compat.h> #include "compat_qseecom.h" #include <linux/kthread.h> #define QSEECOM_DEV "qseecom" #define QSEOS_VERSION_14 0x14 Loading Loading @@ -140,6 +141,11 @@ enum qseecom_ce_hw_instance { CLK_INVALID, }; 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 @@ -298,6 +304,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 @@ -1149,8 +1158,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); return -EINVAL; Loading Loading @@ -1246,8 +1261,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 @@ -1263,9 +1284,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 @@ -1304,6 +1322,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 @@ -1361,6 +1383,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 @@ -3297,7 +3343,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("cache operation failed %d\n", ret2); return ret2; } __qseecom_processing_pending_lsnr_unregister(); return ret; } Loading Loading @@ -4515,7 +4560,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 @@ -4689,7 +4734,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 @@ -4739,7 +4784,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 @@ -7057,7 +7102,7 @@ static inline 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 @@ -8657,6 +8702,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 @@ -8857,6 +8903,17 @@ static int qseecom_probe(struct platform_device *pdev) if (!qseecom.qsee_perf_client) pr_err("Unable to register bus client\n"); /*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 @@ -8973,6 +9030,8 @@ static int qseecom_remove(struct platform_device *pdev) ion_client_destroy(qseecom.ion_clnt); 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 @@ -50,6 +50,7 @@ #include <linux/compat.h> #include "compat_qseecom.h" #include <linux/kthread.h> #define QSEECOM_DEV "qseecom" #define QSEOS_VERSION_14 0x14 Loading Loading @@ -140,6 +141,11 @@ enum qseecom_ce_hw_instance { CLK_INVALID, }; 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 @@ -298,6 +304,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 @@ -1149,8 +1158,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); return -EINVAL; Loading Loading @@ -1246,8 +1261,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 @@ -1263,9 +1284,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 @@ -1304,6 +1322,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 @@ -1361,6 +1383,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 @@ -3297,7 +3343,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("cache operation failed %d\n", ret2); return ret2; } __qseecom_processing_pending_lsnr_unregister(); return ret; } Loading Loading @@ -4515,7 +4560,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 @@ -4689,7 +4734,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 @@ -4739,7 +4784,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 @@ -7057,7 +7102,7 @@ static inline 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 @@ -8657,6 +8702,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 @@ -8857,6 +8903,17 @@ static int qseecom_probe(struct platform_device *pdev) if (!qseecom.qsee_perf_client) pr_err("Unable to register bus client\n"); /*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 @@ -8973,6 +9030,8 @@ static int qseecom_remove(struct platform_device *pdev) ion_client_destroy(qseecom.ion_clnt); kthread_stop(qseecom.unregister_lsnr_kthread_task); cdev_del(&qseecom.cdev); device_destroy(driver_class, qseecom_device_no); Loading