From 13d99673203085f88fcc690231da96f46b6f695a Mon Sep 17 00:00:00 2001 From: Ramesh Masavarapu Date: Tue, 17 Jul 2012 11:05:15 -0700 Subject: [PATCH] qseecom: Support multiple clients. When multiple clients request qseecom to load an application, an app id is assigned. If the request is to load an app that already exists in qsee, the app id should return to the qseecom library. Returning the app id was done in the qseecom_load_app() but not done in the qseecom_query_app_loaded(). This change fixes the issue when multiple clients request to load the same app in qsee. Change-Id: Icaa5053906b61ace1d257ff1c96308cc89e3a9cc Signed-off-by: Ramesh Masavarapu --- drivers/misc/qseecom.c | 213 +++++++++++++++++++++------------------- include/linux/qseecom.h | 2 + 2 files changed, 116 insertions(+), 99 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index d4eb6e03b36..8354aa81f35 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -609,10 +609,24 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req) return -EINVAL; } - if (resp.result == QSEOS_RESULT_FAILURE) - return 0; - else - return resp.data; + if (resp.result == QSEOS_RESULT_FAILURE) { + return 0; + } else { + switch (resp.resp_type) { + /*qsee returned listener type response */ + case QSEOS_LISTENER_ID: + pr_err("resp type is of listener type instead of app"); + return -EINVAL; + break; + case QSEOS_APP_ID: + return resp.data; + default: + pr_err("invalid resp type (%d) from qsee", + resp.resp_type); + return -ENODEV; + break; + } + } } static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) @@ -627,6 +641,8 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) uint32_t len; struct qseecom_command_scm_resp resp; struct qseecom_check_app_ireq req; + struct qseecom_load_app_ireq load_req; + /* Copy the relevant information needed for loading the image */ if (__copy_from_user(&load_img_req, (void __user *)argp, @@ -642,108 +658,86 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND; memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE); - ret = __qseecom_check_app_exists(req); - if (ret < 0) - return ret; - else - app_id = ret; - - if (app_id) { - pr_warn("App id %d (%s) already exists\n", app_id, + pr_warn("App (%s) does not exist, loading apps for first time\n", (char *)(req.app_name)); - spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); - list_for_each_entry(entry, - &qseecom.registered_app_list_head, list){ - if (entry->app_id == app_id) { - entry->ref_cnt++; - break; - } - } - spin_unlock_irqrestore( - &qseecom.registered_app_list_lock, flags); - } else { - struct qseecom_load_app_ireq load_req; - - pr_warn("App (%s) does not exist, loading apps for first time\n", - (char *)(req.app_name)); - /* Get the handle of the shared fd */ - ihandle = ion_import_dma_buf(qseecom.ion_clnt, + /* Get the handle of the shared fd */ + ihandle = ion_import_dma_buf(qseecom.ion_clnt, load_img_req.ifd_data_fd); - if (IS_ERR_OR_NULL(ihandle)) { - pr_err("Ion client could not retrieve the handle\n"); - qsee_disable_clock_vote(CLK_SFPB); - return -ENOMEM; - } + if (IS_ERR_OR_NULL(ihandle)) { + pr_err("Ion client could not retrieve the handle\n"); + qsee_disable_clock_vote(CLK_SFPB); + return -ENOMEM; + } - /* Get the physical address of the ION BUF */ - ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len); + /* Get the physical address of the ION BUF */ + ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len); - /* Populate the structure for sending scm call to load image */ - load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND; - load_req.mdt_len = load_img_req.mdt_len; - load_req.img_len = load_img_req.img_len; - load_req.phy_addr = pa; + /* Populate the structure for sending scm call to load image */ + load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND; + load_req.mdt_len = load_img_req.mdt_len; + load_req.img_len = load_img_req.img_len; + load_req.phy_addr = pa; - /* SCM_CALL to load the app and get the app_id back */ - ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req, - sizeof(struct qseecom_load_app_ireq), - &resp, sizeof(resp)); - if (ret) { - pr_err("scm_call to load app failed\n"); - return -EINVAL; - } + /* SCM_CALL to load the app and get the app_id back */ + ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req, + sizeof(struct qseecom_load_app_ireq), + &resp, sizeof(resp)); + if (ret) { + pr_err("scm_call to load app failed\n"); + return -EINVAL; + } - if (resp.result == QSEOS_RESULT_FAILURE) { - pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n"); - if (!IS_ERR_OR_NULL(ihandle)) - ion_free(qseecom.ion_clnt, ihandle); - qsee_disable_clock_vote(CLK_SFPB); - return -EFAULT; - } - - if (resp.result == QSEOS_RESULT_INCOMPLETE) { - ret = __qseecom_process_incomplete_cmd(data, &resp); - if (ret) { - pr_err("process_incomplete_cmd failed err: %d\n", - ret); - if (!IS_ERR_OR_NULL(ihandle)) - ion_free(qseecom.ion_clnt, ihandle); - qsee_disable_clock_vote(CLK_SFPB); - return ret; - } - } - if (resp.result != QSEOS_RESULT_SUCCESS) { - pr_err("scm_call failed resp.result unknown, %d\n", - resp.result); - if (!IS_ERR_OR_NULL(ihandle)) - ion_free(qseecom.ion_clnt, ihandle); - qsee_disable_clock_vote(CLK_SFPB); - return -EFAULT; - } - - app_id = resp.data; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - pr_err("kmalloc failed\n"); - qsee_disable_clock_vote(CLK_SFPB); - return -ENOMEM; - } - entry->app_id = app_id; - entry->ref_cnt = 1; - - /* Deallocate the handle */ + if (resp.result == QSEOS_RESULT_FAILURE) { + pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n"); if (!IS_ERR_OR_NULL(ihandle)) ion_free(qseecom.ion_clnt, ihandle); - - spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); - list_add_tail(&entry->list, &qseecom.registered_app_list_head); - spin_unlock_irqrestore(&qseecom.registered_app_list_lock, - flags); - - pr_warn("App with id %d (%s) now loaded\n", app_id, - (char *)(req.app_name)); + qsee_disable_clock_vote(CLK_SFPB); + return -EFAULT; } + + if (resp.result == QSEOS_RESULT_INCOMPLETE) { + ret = __qseecom_process_incomplete_cmd(data, &resp); + if (ret) { + pr_err("process_incomplete_cmd failed err: %d\n", + ret); + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); + qsee_disable_clock_vote(CLK_SFPB); + return ret; + } + } + + if (resp.result != QSEOS_RESULT_SUCCESS) { + pr_err("scm_call failed resp.result unknown, %d\n", + resp.result); + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); + qsee_disable_clock_vote(CLK_SFPB); + return -EFAULT; + } + + app_id = resp.data; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + pr_err("kmalloc failed\n"); + qsee_disable_clock_vote(CLK_SFPB); + return -ENOMEM; + } + entry->app_id = app_id; + entry->ref_cnt = 1; + + /* Deallocate the handle */ + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); + + spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); + list_add_tail(&entry->list, &qseecom.registered_app_list_head); + spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); + + pr_warn("App with id %d (%s) now loaded\n", app_id, + (char *)(req.app_name)); + data->client.app_id = app_id; load_img_req.app_id = app_id; if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { @@ -1432,6 +1426,8 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, int32_t ret; struct qseecom_qseos_app_load_query query_req; struct qseecom_check_app_ireq req; + struct qseecom_registered_app_list *entry = NULL; + unsigned long flags = 0; /* Copy the relevant information needed for loading the image */ if (__copy_from_user(&query_req, @@ -1445,11 +1441,30 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, memcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE); ret = __qseecom_check_app_exists(req); - if (ret == -EINVAL) { + + if ((ret == -EINVAL) || (ret == -ENODEV)) { pr_err(" scm call to check if app is loaded failed"); return ret; /* scm call failed */ } else if (ret > 0) { - pr_err("app is already loaded in QSEE"); + pr_warn("App id %d (%s) already exists\n", ret, + (char *)(req.app_name)); + spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); + list_for_each_entry(entry, + &qseecom.registered_app_list_head, list){ + if (entry->app_id == ret) { + entry->ref_cnt++; + break; + } + } + spin_unlock_irqrestore( + &qseecom.registered_app_list_lock, flags); + data->client.app_id = ret; + query_req.app_id = ret; + + if (copy_to_user(argp, &query_req, sizeof(query_req))) { + pr_err("copy_to_user failed\n"); + return -EFAULT; + } return -EEXIST; /* app already loaded */ } else { return 0; /* app not loaded */ diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h index 0fcf96f7e61..b0f089b1d58 100644 --- a/include/linux/qseecom.h +++ b/include/linux/qseecom.h @@ -110,9 +110,11 @@ struct qseecom_qseos_version_req { /* * struct qseecom_qseos_app_load_query - verify if app is loaded in qsee * @app_name[MAX_APP_NAME_SIZE]- name of the app. + * @app_id - app id. */ struct qseecom_qseos_app_load_query { char app_name[MAX_APP_NAME_SIZE]; /* in */ + int app_id; /* out */ }; #define QSEECOM_IOC_MAGIC 0x97