qseecom: Add support to handle multiple app load & unload
Media server is associated with multiple apps on TZ-side. Unloading a single app for clean up is not enought. QSEECOM needs to handle the app load & unload of multiple apps associated with the client. During app_load & app_unload along with app_id, app_name should also be checked. Besides, keymaster will not be unloaded. Change-Id: Iea53362a21e359e54e40a0a93688a05264cfde5c Signed-off-by: Hariprasad Dhalinarasimha <hnamgund@codeaurora.org> Signed-off-by: Zhen Kong <zkong@codeaurora.org>
This commit is contained in:
parent
03e523358a
commit
0ae872ae04
|
@ -176,6 +176,7 @@ struct qseecom_registered_app_list {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
u32 app_id;
|
u32 app_id;
|
||||||
u32 ref_cnt;
|
u32 ref_cnt;
|
||||||
|
char app_name[MAX_APP_NAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qseecom_registered_kclient_list {
|
struct qseecom_registered_kclient_list {
|
||||||
|
@ -201,7 +202,6 @@ struct qseecom_control {
|
||||||
struct device *pdev;
|
struct device *pdev;
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
|
|
||||||
bool uclient_shutdown_app;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qseecom_client_handle {
|
struct qseecom_client_handle {
|
||||||
|
@ -211,6 +211,7 @@ struct qseecom_client_handle {
|
||||||
uint32_t user_virt_sb_base;
|
uint32_t user_virt_sb_base;
|
||||||
size_t sb_length;
|
size_t sb_length;
|
||||||
struct ion_handle *ihandle; /* Retrieve phy addr */
|
struct ion_handle *ihandle; /* Retrieve phy addr */
|
||||||
|
char app_name[MAX_APP_NAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qseecom_listener_handle {
|
struct qseecom_listener_handle {
|
||||||
|
@ -795,7 +796,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
|
||||||
}
|
}
|
||||||
entry->app_id = app_id;
|
entry->app_id = app_id;
|
||||||
entry->ref_cnt = 1;
|
entry->ref_cnt = 1;
|
||||||
|
memset((void *)entry->app_name, 0, MAX_APP_NAME_SIZE);
|
||||||
|
memcpy((void *)entry->app_name,
|
||||||
|
(void *)load_img_req.img_name, MAX_APP_NAME_SIZE);
|
||||||
/* Deallocate the handle */
|
/* Deallocate the handle */
|
||||||
if (!IS_ERR_OR_NULL(ihandle))
|
if (!IS_ERR_OR_NULL(ihandle))
|
||||||
ion_free(qseecom.ion_clnt, ihandle);
|
ion_free(qseecom.ion_clnt, ihandle);
|
||||||
|
@ -809,6 +812,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
|
||||||
(char *)(load_img_req.img_name));
|
(char *)(load_img_req.img_name));
|
||||||
}
|
}
|
||||||
data->client.app_id = app_id;
|
data->client.app_id = app_id;
|
||||||
|
memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
|
||||||
|
memcpy((void *)data->client.app_name,
|
||||||
|
(void *)load_img_req.img_name, MAX_APP_NAME_SIZE);
|
||||||
load_img_req.app_id = app_id;
|
load_img_req.app_id = app_id;
|
||||||
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
|
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
|
||||||
pr_err("copy_to_user failed\n");
|
pr_err("copy_to_user failed\n");
|
||||||
|
@ -847,58 +853,64 @@ static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qseecom_unload_app(struct qseecom_dev_handle *data,
|
static int qseecom_unload_app(struct qseecom_dev_handle *data,
|
||||||
bool uclient_release)
|
bool app_crash)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned long flags1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct qseecom_command_scm_resp resp;
|
struct qseecom_command_scm_resp resp;
|
||||||
struct qseecom_registered_app_list *ptr_app;
|
struct qseecom_registered_app_list *ptr_app = NULL;
|
||||||
bool unload = false;
|
bool unload = false;
|
||||||
bool found_app = false;
|
bool found_app = false;
|
||||||
|
bool found_dead_app = false;
|
||||||
|
|
||||||
if ((qseecom.qseos_version == QSEOS_VERSION_14) &&
|
if (!memcmp(data->client.app_name, "keymaste", strlen("keymaste"))) {
|
||||||
(data->client.app_id > 0)) {
|
pr_warn("Do not unload keymaster app from tz\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->client.app_id > 0) {
|
||||||
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
|
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
|
||||||
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
|
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
|
||||||
list) {
|
list) {
|
||||||
if (ptr_app->app_id == data->client.app_id) {
|
if (ptr_app->app_id == data->client.app_id) {
|
||||||
|
if (!memcmp((void *)ptr_app->app_name,
|
||||||
|
(void *)data->client.app_name,
|
||||||
|
strlen(data->client.app_name))) {
|
||||||
found_app = true;
|
found_app = true;
|
||||||
if ((uclient_release) &&
|
if (app_crash) {
|
||||||
(!qseecom.uclient_shutdown_app)) {
|
|
||||||
ptr_app->ref_cnt = 0;
|
|
||||||
unload = true;
|
unload = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (ptr_app->ref_cnt == 1) {
|
if (ptr_app->ref_cnt == 1) {
|
||||||
unload = true;
|
unload = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr_app->ref_cnt--;
|
found_dead_app = true;
|
||||||
pr_debug("Can't unload app(%d) inuse\n",
|
|
||||||
ptr_app->app_id);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
|
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
|
||||||
flags);
|
flags);
|
||||||
if (found_app == false) {
|
if (found_app == false && found_dead_app == false) {
|
||||||
pr_err("Cannot find app with id = %d\n",
|
pr_err("Cannot find app with id = %d (%s)\n",
|
||||||
data->client.app_id);
|
data->client.app_id,
|
||||||
|
(char *)data->client.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((unload) && (qseecom.qseos_version == QSEOS_VERSION_14)) {
|
if (found_dead_app) {
|
||||||
struct qseecom_unload_app_ireq req;
|
pr_warn("cleanup dead app: app_id %d(%s)\n", data->client.app_id,
|
||||||
|
(char *)data->client.app_name);
|
||||||
__qseecom_cleanup_app(data);
|
__qseecom_cleanup_app(data);
|
||||||
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
|
}
|
||||||
list_del(&ptr_app->list);
|
|
||||||
kzfree(ptr_app);
|
if (unload) {
|
||||||
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
|
struct qseecom_unload_app_ireq req;
|
||||||
flags);
|
|
||||||
/* Populate the structure for sending scm call to load image */
|
/* Populate the structure for sending scm call to load image */
|
||||||
req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND;
|
req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND;
|
||||||
req.app_id = data->client.app_id;
|
req.app_id = data->client.app_id;
|
||||||
|
@ -914,6 +926,15 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
|
||||||
} else {
|
} else {
|
||||||
pr_warn("App id %d now unloaded\n", req.app_id);
|
pr_warn("App id %d now unloaded\n", req.app_id);
|
||||||
}
|
}
|
||||||
|
if (resp.result == QSEOS_RESULT_FAILURE) {
|
||||||
|
pr_err("app (%d) unload_failed!!\n",
|
||||||
|
data->client.app_id);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
if (resp.result == QSEOS_RESULT_SUCCESS)
|
||||||
|
pr_info("App (%d) is unloaded!!\n",
|
||||||
|
data->client.app_id);
|
||||||
|
__qseecom_cleanup_app(data);
|
||||||
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
|
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
|
||||||
ret = __qseecom_process_incomplete_cmd(data, &resp);
|
ret = __qseecom_process_incomplete_cmd(data, &resp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -936,6 +957,28 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found_app) {
|
||||||
|
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
|
||||||
|
if (app_crash) {
|
||||||
|
ptr_app->ref_cnt = 0;
|
||||||
|
pr_debug("app_crash: ref_count = 0\n");
|
||||||
|
} else {
|
||||||
|
if (ptr_app->ref_cnt == 1) {
|
||||||
|
ptr_app->ref_cnt = 0;
|
||||||
|
pr_info("ref_count set to 0\n");
|
||||||
|
} else {
|
||||||
|
ptr_app->ref_cnt--;
|
||||||
|
pr_info("Can't unload app(%d) inuse\n",
|
||||||
|
ptr_app->app_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unload) {
|
||||||
|
list_del(&ptr_app->list);
|
||||||
|
kzfree(ptr_app);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
|
||||||
|
flags1);
|
||||||
|
}
|
||||||
qseecom_unmap_ion_allocated_memory(data);
|
qseecom_unmap_ion_allocated_memory(data);
|
||||||
data->released = true;
|
data->released = true;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1116,9 +1159,32 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
|
||||||
u32 reqd_len_sb_in = 0;
|
u32 reqd_len_sb_in = 0;
|
||||||
struct qseecom_client_send_data_ireq send_data_req;
|
struct qseecom_client_send_data_ireq send_data_req;
|
||||||
struct qseecom_command_scm_resp resp;
|
struct qseecom_command_scm_resp resp;
|
||||||
|
unsigned long flags;
|
||||||
|
struct qseecom_registered_app_list *ptr_app;
|
||||||
|
bool found_app = false;
|
||||||
|
|
||||||
reqd_len_sb_in = req->cmd_req_len + req->resp_len;
|
reqd_len_sb_in = req->cmd_req_len + req->resp_len;
|
||||||
|
|
||||||
|
/* find app_id & img_name from list */
|
||||||
|
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
|
||||||
|
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
|
||||||
|
list) {
|
||||||
|
if ((ptr_app->app_id == data->client.app_id) &&
|
||||||
|
(!memcmp((void *)ptr_app->app_name,
|
||||||
|
(void *)data->client.app_name,
|
||||||
|
strlen(data->client.app_name)))) {
|
||||||
|
found_app = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
|
||||||
|
|
||||||
|
if (!found_app) {
|
||||||
|
pr_err("app_id %d (%s) is not found\n", data->client.app_id,
|
||||||
|
(char *)data->client.app_name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
|
send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
|
||||||
send_data_req.app_id = data->client.app_id;
|
send_data_req.app_id = data->client.app_id;
|
||||||
send_data_req.req_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
|
send_data_req.req_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
|
||||||
|
@ -2084,7 +2150,9 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
|
||||||
&qseecom.registered_app_list_lock, flags);
|
&qseecom.registered_app_list_lock, flags);
|
||||||
data->client.app_id = ret;
|
data->client.app_id = ret;
|
||||||
query_req.app_id = ret;
|
query_req.app_id = ret;
|
||||||
|
memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
|
||||||
|
memcpy((void *)data->client.app_name,
|
||||||
|
(void *)query_req.app_name, MAX_APP_NAME_SIZE);
|
||||||
if (copy_to_user(argp, &query_req, sizeof(query_req))) {
|
if (copy_to_user(argp, &query_req, sizeof(query_req))) {
|
||||||
pr_err("copy_to_user failed\n");
|
pr_err("copy_to_user failed\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -2196,7 +2264,6 @@ static long qseecom_ioctl(struct file *file, unsigned cmd,
|
||||||
pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data);
|
pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data);
|
||||||
mutex_lock(&app_access_lock);
|
mutex_lock(&app_access_lock);
|
||||||
atomic_inc(&data->ioctl_count);
|
atomic_inc(&data->ioctl_count);
|
||||||
qseecom.uclient_shutdown_app = true;
|
|
||||||
ret = qseecom_unload_app(data, false);
|
ret = qseecom_unload_app(data, false);
|
||||||
atomic_dec(&data->ioctl_count);
|
atomic_dec(&data->ioctl_count);
|
||||||
mutex_unlock(&app_access_lock);
|
mutex_unlock(&app_access_lock);
|
||||||
|
@ -2293,6 +2360,7 @@ static int qseecom_open(struct inode *inode, struct file *file)
|
||||||
data->abort = 0;
|
data->abort = 0;
|
||||||
data->type = QSEECOM_GENERIC;
|
data->type = QSEECOM_GENERIC;
|
||||||
data->released = false;
|
data->released = false;
|
||||||
|
memset((void *)data->client.app_name, 0, MAX_APP_NAME_SIZE);
|
||||||
init_waitqueue_head(&data->abort_wq);
|
init_waitqueue_head(&data->abort_wq);
|
||||||
atomic_set(&data->ioctl_count, 0);
|
atomic_set(&data->ioctl_count, 0);
|
||||||
if (qseecom.qseos_version == QSEOS_VERSION_13) {
|
if (qseecom.qseos_version == QSEOS_VERSION_13) {
|
||||||
|
@ -2349,7 +2417,6 @@ static int qseecom_release(struct inode *inode, struct file *file)
|
||||||
kfree(data);
|
kfree(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
qseecom.uclient_shutdown_app = false;
|
|
||||||
}
|
}
|
||||||
if (qseecom.qseos_version == QSEOS_VERSION_13) {
|
if (qseecom.qseos_version == QSEOS_VERSION_13) {
|
||||||
mutex_lock(&pil_access_lock);
|
mutex_lock(&pil_access_lock);
|
||||||
|
|
Loading…
Reference in New Issue