qseecom: Fix issues with qssecom_remove/exit APIs
Clean-up the qseecom_remove() function by removing the null pointer
dereference. Change the logic by removing the unnecessary code and
also modified the qseecom_exit() function with proper calls.
Change-Id: Ibcca1b3c2c37024661505de2550e202b507703aa
Signed-off-by: AnilKumar Chimata <anilc@codeaurora.org>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index ac67c9d..810a57d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -138,7 +138,6 @@
static struct class *driver_class;
static dev_t qseecom_device_no;
-static struct cdev qseecom_cdev;
/* Data structures used in legacy support */
static void *pil;
@@ -192,6 +191,7 @@
uint32_t qseos_version;
struct device *pdev;
+ struct cdev cdev;
};
struct qseecom_client_handle {
@@ -2354,7 +2354,7 @@
if (IS_ERR(driver_class)) {
rc = -ENOMEM;
pr_err("class_create failed %d\n", rc);
- goto unregister_chrdev_region;
+ goto exit_unreg_chrdev_region;
}
class_dev = device_create(driver_class, NULL, qseecom_device_no, NULL,
@@ -2362,16 +2362,16 @@
if (!class_dev) {
pr_err("class_device_create failed %d\n", rc);
rc = -ENOMEM;
- goto class_destroy;
+ goto exit_destroy_class;
}
- cdev_init(&qseecom_cdev, &qseecom_fops);
- qseecom_cdev.owner = THIS_MODULE;
+ cdev_init(&qseecom.cdev, &qseecom_fops);
+ qseecom.cdev.owner = THIS_MODULE;
- rc = cdev_add(&qseecom_cdev, MKDEV(MAJOR(qseecom_device_no), 0), 1);
+ rc = cdev_add(&qseecom.cdev, MKDEV(MAJOR(qseecom_device_no), 0), 1);
if (rc < 0) {
pr_err("cdev_add failed %d\n", rc);
- goto err;
+ goto exit_destroy_device;
}
INIT_LIST_HEAD(&qseecom.registered_listener_list_head);
@@ -2387,7 +2387,7 @@
&qsee_not_legacy, sizeof(qsee_not_legacy));
if (rc) {
pr_err("Failed to retrieve QSEE version information %d\n", rc);
- goto err;
+ goto exit_del_cdev;
}
if (qsee_not_legacy)
qseecom.qseos_version = QSEOS_VERSION_14;
@@ -2403,14 +2403,14 @@
if (qseecom.ion_clnt == NULL) {
pr_err("Ion client cannot be created\n");
rc = -ENOMEM;
- goto err;
+ goto exit_del_cdev;
}
/* register client for bus scaling */
if (pdev->dev.of_node) {
ret = __qseecom_init_clk();
if (ret)
- goto err;
+ goto exit_destroy_ion_client;
qseecom_platform_support = (struct msm_bus_scale_pdata *)
msm_bus_cl_get_pdata(pdev);
} else {
@@ -2424,11 +2424,16 @@
if (!qsee_perf_client)
pr_err("Unable to register bus client\n");
return 0;
-err:
+
+exit_destroy_ion_client:
+ ion_client_destroy(qseecom.ion_clnt);
+exit_del_cdev:
+ cdev_del(&qseecom.cdev);
+exit_destroy_device:
device_destroy(driver_class, qseecom_device_no);
-class_destroy:
+exit_destroy_class:
class_destroy(driver_class);
-unregister_chrdev_region:
+exit_unreg_chrdev_region:
unregister_chrdev_region(qseecom_device_no, 1);
return rc;
}
@@ -2439,57 +2444,57 @@
unsigned long flags = 0;
int ret = 0;
- if (pdev->dev.platform_data != NULL)
- msm_bus_scale_unregister_client(qsee_perf_client);
-
spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
- kclient = list_entry((&qseecom.registered_kclient_list_head)->next,
- struct qseecom_registered_kclient_list, list);
- if (list_empty(&kclient->list)) {
- spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
- flags);
- return 0;
- }
+
list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
- list) {
- if (kclient)
- list_del(&kclient->list);
- break;
- }
- spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+ list) {
+ if (!kclient)
+ goto exit_irqrestore;
+ /* Break the loop if client handle is NULL */
+ if (!kclient->handle)
+ goto exit_free_kclient;
- while (kclient->handle != NULL) {
+ if (list_empty(&kclient->list))
+ goto exit_free_kc_handle;
+
+ list_del(&kclient->list);
ret = qseecom_unload_app(kclient->handle->dev);
- if (ret == 0) {
+ if (!ret) {
kzfree(kclient->handle->dev);
kzfree(kclient->handle);
kzfree(kclient);
}
- spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
- kclient = list_entry(
- (&qseecom.registered_kclient_list_head)->next,
- struct qseecom_registered_kclient_list, list);
- if (list_empty(&kclient->list)) {
- spin_unlock_irqrestore(
- &qseecom.registered_kclient_list_lock, flags);
- return 0;
- }
- list_for_each_entry(kclient,
- &qseecom.registered_kclient_list_head, list) {
- if (kclient)
- list_del(&kclient->list);
- break;
- }
- spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
- flags);
- if (!kclient) {
- ret = 0;
- break;
- }
}
+
+exit_free_kc_handle:
+ kzfree(kclient->handle);
+exit_free_kclient:
+ kzfree(kclient);
+exit_irqrestore:
+ spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+
+ if (qsee_perf_client)
+ msm_bus_scale_client_update_request(qsee_perf_client, 0);
+
+ if (pdev->dev.platform_data)
+ msm_bus_scale_unregister_client(qsee_perf_client);
+
+ if (pdev->dev.of_node)
+ __qseecom_disable_clk();
+
+ ion_client_destroy(qseecom.ion_clnt);
+
+ cdev_del(&qseecom.cdev);
+
+ device_destroy(driver_class, qseecom_device_no);
+
+ class_destroy(driver_class);
+
+ unregister_chrdev_region(qseecom_device_no, 1);
+
return ret;
-};
+}
static struct of_device_id qseecom_match[] = {
{
@@ -2515,13 +2520,7 @@
static void __devexit qseecom_exit(void)
{
-
- __qseecom_disable_clk();
-
- device_destroy(driver_class, qseecom_device_no);
- class_destroy(driver_class);
- unregister_chrdev_region(qseecom_device_no, 1);
- ion_client_destroy(qseecom.ion_clnt);
+ platform_driver_unregister(&qseecom_plat_driver);
}
MODULE_LICENSE("GPL v2");