diff --git a/qseecom/qseecom.c b/qseecom/qseecom.c index 1672afee8e..be20de0959 100644 --- a/qseecom/qseecom.c +++ b/qseecom/qseecom.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -379,6 +380,7 @@ struct qseecom_control { struct list_head unload_app_pending_list_head; struct task_struct *unload_app_kthread_task; + struct notifier_block reboot_nb; wait_queue_head_t unload_app_kthread_wq; atomic_t unload_app_kthread_state; bool no_user_contig_mem_support; @@ -9270,6 +9272,47 @@ static void qseecom_release_ce_data(void) } } +static int qseecom_reboot_worker(struct notifier_block *nb, unsigned long val, void *data) +{ + struct qseecom_registered_listener_list *entry; + + /* Mark all the listener as abort since system is going + * for a reboot so every pending listener request should + * be aborted. + */ + list_for_each_entry(entry, + &qseecom.registered_listener_list_head, list) { + entry->abort = 1; + } + + /* stop CA thread waiting for listener response */ + wake_up_interruptible_all(&qseecom.send_resp_wq); + + /* Assumption is system going in reboot + * every registered listener from userspace waiting + * on event interruptible will receive interrupt as + * TASK_INTERRUPTIBLE flag will be set for them + */ + + return 0; +} +static int qseecom_register_reboot_notifier(void) +{ + int rc = 0; + + /* Registering reboot notifier for resource cleanup at reboot. + * Current implementation is for listener use case, + * it can be extended to App also in case of any corner + * case issue found. + */ + + qseecom.reboot_nb.notifier_call = qseecom_reboot_worker; + rc = register_reboot_notifier(&(qseecom.reboot_nb)); + if (rc) + pr_err("failed to register reboot notifier\n"); + return rc; +} + static int qseecom_init_dev(struct platform_device *pdev) { int rc = 0; @@ -9324,6 +9367,19 @@ static int qseecom_init_dev(struct platform_device *pdev) pr_err("Failed to initialize reserved mem, ret %d\n", rc); goto exit_del_cdev; } + + rc = qseecom_register_reboot_notifier(); + if (rc) { + pr_err("failed in registering reboot notifier %d\n", rc); + /* exit even if notifier registration fail. + * Although, thats not a functional failure from qseecom + * driver prespective but this registration + * failure will cause more complex issue at the + * time of reboot or possibly halt the reboot. + */ + goto exit_del_cdev; + } + return 0; exit_del_cdev: @@ -9342,6 +9398,7 @@ static void qseecom_deinit_dev(void) { kfree(qseecom.dev->dma_parms); qseecom.dev->dma_parms = NULL; + unregister_reboot_notifier(&(qseecom.reboot_nb)); cdev_del(&qseecom.cdev); device_destroy(qseecom.driver_class, qseecom.qseecom_device_no); class_destroy(qseecom.driver_class);