qseecom: Unload the app upon receiving qseecom_release.

Upon receiving qseecom_release() app corresponding to the app id
needs to be shutdown.This is applicable to user space clients as well.

Change-Id: Ie659a9409f8470b7ed4a5088e6779b50c5dc1cca
Signed-off-by: Hariprasad Dhalinarasimha <hnamgund@codeaurora.org>
Signed-off-by: Zhen Kong <zkong@codeaurora.org>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index f269159..12b6fc8 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -200,6 +200,8 @@
 	uint32_t          qseos_version;
 	struct device *pdev;
 	struct cdev cdev;
+
+	bool uclient_shutdown_app;
 };
 
 struct qseecom_client_handle {
@@ -834,7 +836,8 @@
 	return ret;
 }
 
-static int qseecom_unload_app(struct qseecom_dev_handle *data)
+static int qseecom_unload_app(struct qseecom_dev_handle *data,
+				bool uclient_release)
 {
 	unsigned long flags;
 	int ret = 0;
@@ -850,14 +853,21 @@
 								list) {
 			if (ptr_app->app_id == data->client.app_id) {
 				found_app = true;
-				if (ptr_app->ref_cnt == 1) {
+				if ((uclient_release) &&
+					(!qseecom.uclient_shutdown_app)) {
+					ptr_app->ref_cnt = 0;
 					unload = true;
 					break;
 				} else {
-					ptr_app->ref_cnt--;
-					pr_warn("Can't unload app(%d) inuse\n",
+					if (ptr_app->ref_cnt == 1) {
+						unload = true;
+						break;
+					} else {
+						ptr_app->ref_cnt--;
+						pr_debug("Can't unload app(%d) inuse\n",
 							ptr_app->app_id);
-					break;
+						break;
+					}
 				}
 			}
 		}
@@ -1639,7 +1649,7 @@
 	if (!found_handle)
 		pr_err("Unable to find the handle, exiting\n");
 	else
-		ret = qseecom_unload_app(data);
+		ret = qseecom_unload_app(data, false);
 	if (ret == 0) {
 		kzfree(data);
 		kzfree(*handle);
@@ -2145,7 +2155,8 @@
 	case QSEECOM_IOCTL_UNLOAD_APP_REQ: {
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
-		ret = qseecom_unload_app(data);
+		qseecom.uclient_shutdown_app = true;
+		ret = qseecom_unload_app(data, false);
 		atomic_dec(&data->ioctl_count);
 		mutex_unlock(&app_access_lock);
 		if (ret)
@@ -2272,7 +2283,7 @@
 			ret = qseecom_unregister_listener(data);
 			break;
 		case QSEECOM_CLIENT_APP:
-			ret = qseecom_unload_app(data);
+			ret = qseecom_unload_app(data, true);
 			break;
 		case QSEECOM_SECURE_SERVICE:
 			ret = qseecom_unmap_ion_allocated_memory(data);
@@ -2284,10 +2295,17 @@
 		case QSEECOM_UNAVAILABLE_CLIENT_APP:
 			break;
 		default:
+			ret = -EINVAL;
 			pr_err("Unsupported clnt_handle_type %d",
 				data->type);
 			break;
 		}
+		if (ret) {
+			pr_err("Close failed\n");
+			kfree(data);
+			return ret;
+		}
+		qseecom.uclient_shutdown_app = false;
 	}
 	if (qseecom.qseos_version == QSEOS_VERSION_13) {
 		mutex_lock(&pil_access_lock);
@@ -2556,7 +2574,7 @@
 			goto exit_free_kc_handle;
 
 		list_del(&kclient->list);
-		ret = qseecom_unload_app(kclient->handle->dev);
+		ret = qseecom_unload_app(kclient->handle->dev, false);
 		if (!ret) {
 			kzfree(kclient->handle->dev);
 			kzfree(kclient->handle);