From b682fbfef021b6f24e034a73bdf76ef71c2accc1 Mon Sep 17 00:00:00 2001 From: Indranil Pradhan Date: Fri, 23 Jun 2023 15:24:44 +0530 Subject: [PATCH] securemsm-kernel: Add reboot notifier for resource cleanup at reboot Added reboot notifier function to do resource clean up during reboot as mutliple issues during reboot were noticed where release call was not invoked by OS for qseecom driver. This lead listener req to wait for for response which hold reboot for infinite time. Test Cases: 1. Ran HDCP_denit at reboot to check reboot stuck. 2. Mutliple Reboots. Change-Id: I7917cf9a89feca731e479538e7f4fa0671a29edd Signed-off-by: Indranil Pradhan --- qseecom/qseecom.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) 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);