Răsfoiți Sursa

Merge "securemsm-kernel: Add reboot notifier for resource cleanup at reboot"

qctecmdr 1 an în urmă
părinte
comite
ae47124ef5
1 a modificat fișierele cu 57 adăugiri și 0 ștergeri
  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);