Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8523d8b0 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qseecom: abort all listener threads before listener unregistration"

parents 776ae3d8 89656063
Loading
Loading
Loading
Loading
+80 −81
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ struct qseecom_registered_listener_list {
	wait_queue_head_t          listener_block_app_wq;
	struct sglist_info sglistinfo_ptr[MAX_ION_FD];
	uint32_t sglist_cnt;
	int abort;
};

struct qseecom_registered_app_list {
@@ -1367,6 +1368,23 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
	return ret;
}

static void __qseecom_listener_abort_all(int abort)
{
	struct qseecom_registered_listener_list *entry = NULL;
	unsigned long flags;

	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
	list_for_each_entry(entry,
			&qseecom.registered_listener_list_head, list) {
		pr_debug("set abort %d for listener %d\n",
				abort, entry->svc.listener_id);
		entry->abort = abort;
	}
	if (abort)
		wake_up_interruptible_all(&qseecom.send_resp_wq);
	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
}

static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
{
	int ret = 0;
@@ -1399,6 +1417,7 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
	}

	data->abort = 1;
	ptr_svc->abort = 1;
	wake_up_all(&ptr_svc->rcv_req_wq);

	while (atomic_read(&data->ioctl_count) > 1) {
@@ -1718,12 +1737,13 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
	return ret;
}

static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data)
static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data,
			struct qseecom_registered_listener_list *ptr_svc)
{
	int ret;

	ret = (qseecom.send_resp_flag != 0);
	return ret || data->abort;
	return ret || data->abort || ptr_svc->abort;
}

static int __qseecom_reentrancy_listener_has_sent_rsp(
@@ -1733,62 +1753,7 @@ static int __qseecom_reentrancy_listener_has_sent_rsp(
	int ret;

	ret = (ptr_svc->send_resp_flag != 0);
	return ret || data->abort;
}

static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data,
					struct qseecom_command_scm_resp *resp,
			struct qseecom_client_listener_data_irsp *send_data_rsp,
			struct qseecom_registered_listener_list *ptr_svc,
							uint32_t lstnr)
{
	int ret = 0;

	send_data_rsp->status = QSEOS_RESULT_FAILURE;
	qseecom.send_resp_flag = 0;
	send_data_rsp->qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
	send_data_rsp->listener_id = lstnr;
	if (ptr_svc)
		pr_warn("listener_id:%x, lstnr: %x\n",
					ptr_svc->svc.listener_id, lstnr);
	if (lstnr == RPMB_SERVICE) {
		ret = __qseecom_enable_clk(CLK_QSEE);
		if (ret)
			return ret;
	}

	if (ptr_svc && ptr_svc->dmabuf) {
		ret = qseecom_dmabuf_cache_operations(ptr_svc->dmabuf,
						QSEECOM_CACHE_CLEAN);
		if (ret)
			goto exit;
	}
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, send_data_rsp,
				sizeof(send_data_rsp), resp, sizeof(*resp));
	if (ret) {
		pr_err("scm_call() failed with err: %d (app_id = %d)\n",
						ret, data->client.app_id);
		goto exit;
	}

	if (ptr_svc && ptr_svc->dmabuf) {
		ret = qseecom_dmabuf_cache_operations(ptr_svc->dmabuf,
						QSEECOM_CACHE_INVALIDATE);
		if (ret)
			goto exit;
	}

	if ((resp->result != QSEOS_RESULT_SUCCESS) &&
			(resp->result != QSEOS_RESULT_INCOMPLETE)) {
		pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
				resp->result, data->client.app_id, lstnr);
		ret = -EINVAL;
	}
exit:
	if (lstnr == RPMB_SERVICE)
		__qseecom_disable_clk(CLK_QSEE);

	return ret;
	return ret || data->abort || ptr_svc->abort;
}

static void __qseecom_clean_listener_sglistinfo(
@@ -1839,23 +1804,33 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,

		if (ptr_svc == NULL) {
			pr_err("Listener Svc %d does not exist\n", lstnr);
			__qseecom_qseos_fail_return_resp_tz(data, resp,
					&send_data_rsp, ptr_svc, lstnr);
			return -EINVAL;
			rc = -EINVAL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (!ptr_svc->dmabuf) {
			pr_err("Client dmabuf is not initialized\n");
			__qseecom_qseos_fail_return_resp_tz(data, resp,
					&send_data_rsp, ptr_svc, lstnr);
			return -EINVAL;
			rc = -EINVAL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (ptr_svc->svc.listener_id != lstnr) {
			pr_warn("Service requested does not exist\n");
			__qseecom_qseos_fail_return_resp_tz(data, resp,
					&send_data_rsp, NULL, lstnr);
			return -ERESTARTSYS;
			pr_err("Service %d does not exist\n",
						lstnr);
			rc = -ERESTARTSYS;
			ptr_svc = NULL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (ptr_svc->abort == 1) {
			pr_err("Service %d abort %d\n",
						lstnr, ptr_svc->abort);
			rc = -ENODEV;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}
		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");

@@ -1872,7 +1847,8 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
			 */
			if (!qseecom.qsee_reentrancy_support &&
				!wait_event_freezable(qseecom.send_resp_wq,
				__qseecom_listener_has_sent_rsp(data))) {
				__qseecom_listener_has_sent_rsp(
						data, ptr_svc))) {
				break;
			}

@@ -1886,7 +1862,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,

		/* restore signal mask */
		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
		if (data->abort) {
		if (data->abort || ptr_svc->abort) {
			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
				data->client.app_id, lstnr, ret);
			rc = -ENODEV;
@@ -1894,7 +1870,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
		} else {
			status = QSEOS_RESULT_SUCCESS;
		}

err_resp:
		qseecom.send_resp_flag = 0;
		ptr_svc->send_resp_flag = 0;
		table = ptr_svc->sglistinfo_ptr;
@@ -1957,6 +1933,8 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
		if (ret)
			return ret;

		pr_debug("resp status %d, res= %d, app_id = %d, lstr = %d\n",
			status, resp->result, data->client.app_id, lstnr);
		if ((resp->result != QSEOS_RESULT_SUCCESS) &&
			(resp->result != QSEOS_RESULT_INCOMPLETE)) {
			pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
@@ -2107,7 +2085,7 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
	size_t cmd_len;
	struct sglist_info *table = NULL;

	while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
	while (ret == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
		lstnr = resp->data;
		/*
		 * Wake up blocking lsitener service with the lstnr id
@@ -2128,17 +2106,33 @@ static int __qseecom_reentrancy_process_incomplete_cmd(

		if (ptr_svc == NULL) {
			pr_err("Listener Svc %d does not exist\n", lstnr);
			return -EINVAL;
			rc = -EINVAL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (!ptr_svc->dmabuf) {
			pr_err("Client dmabuf is not initialized\n");
			return -EINVAL;
			rc = -EINVAL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (ptr_svc->svc.listener_id != lstnr) {
			pr_warn("Service requested does not exist\n");
			return -ERESTARTSYS;
			pr_err("Service %d does not exist\n",
						lstnr);
			rc = -ERESTARTSYS;
			ptr_svc = NULL;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}

		if (ptr_svc->abort == 1) {
			pr_err("Service %d abort %d\n",
						lstnr, ptr_svc->abort);
			rc = -ENODEV;
			status = QSEOS_RESULT_FAILURE;
			goto err_resp;
		}
		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");

@@ -2164,7 +2158,7 @@ static int __qseecom_reentrancy_process_incomplete_cmd(

		/* restore signal mask */
		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
		if (data->abort) {
		if (data->abort || ptr_svc->abort) {
			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
				data->client.app_id, lstnr, ret);
			rc = -ENODEV;
@@ -2172,6 +2166,7 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
		} else {
			status  = QSEOS_RESULT_SUCCESS;
		}
err_resp:
		table = ptr_svc->sglistinfo_ptr;
		if (qseecom.qsee_version < QSEE_VERSION_40) {
			send_data_rsp.listener_id  = lstnr;
@@ -3907,7 +3902,7 @@ static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data,
	int ret;

	ret = (svc->rcv_req_flag != 0);
	return ret || data->abort;
	return ret || data->abort || svc->abort;
}

static int qseecom_receive_req(struct qseecom_dev_handle *data)
@@ -3931,7 +3926,7 @@ static int qseecom_receive_req(struct qseecom_dev_handle *data)
			return -ERESTARTSYS;
		}

		if (data->abort) {
		if (data->abort || this_lstnr->abort) {
			pr_err("Aborting Listener Service = %d\n",
					(uint32_t)data->listener.id);
			return -ENODEV;
@@ -6189,7 +6184,7 @@ static int qseecom_update_key_user_info(struct qseecom_dev_handle *data,
}
static int qseecom_is_es_activated(void __user *argp)
{
	struct qseecom_is_es_activated_req req;
	struct qseecom_is_es_activated_req req = {0};
	struct qseecom_command_scm_resp resp;
	int ret;

@@ -7012,12 +7007,14 @@ static inline long qseecom_ioctl(struct file *file,
			break;
		}
		pr_debug("ioctl unregister_listener_req()\n");
		__qseecom_listener_abort_all(1);
		mutex_lock(&app_access_lock);
		atomic_inc(&data->ioctl_count);
		ret = qseecom_unregister_listener(data);
		atomic_dec(&data->ioctl_count);
		wake_up_all(&data->abort_wq);
		mutex_unlock(&app_access_lock);
		__qseecom_listener_abort_all(0);
		if (ret)
			pr_err("failed qseecom_unregister_listener: %d\n", ret);
		break;
@@ -7684,9 +7681,11 @@ static int qseecom_release(struct inode *inode, struct file *file)
			data->type, data->mode, data);
		switch (data->type) {
		case QSEECOM_LISTENER_SERVICE:
			__qseecom_listener_abort_all(1);
			mutex_lock(&app_access_lock);
			ret = qseecom_unregister_listener(data);
			mutex_unlock(&app_access_lock);
			__qseecom_listener_abort_all(0);
			break;
		case QSEECOM_CLIENT_APP:
			mutex_lock(&app_access_lock);