Browse Source

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 <[email protected]>
Indranil Pradhan 2 năm trước cách đây
mục cha
commit
b682fbfef0
1 tập tin đã thay đổi với 57 bổ sung0 xóa
  1. 57 0
      qseecom/qseecom.c

+ 57 - 0
qseecom/qseecom.c

@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/reboot.h>
 #include <linux/platform_device.h>
 #include <linux/debugfs.h>
 #include <linux/cdev.h>
@@ -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);