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

Commit c49af180 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qseecom: fix listener unregister issues"

parents aa719780 c4c162a0
Loading
Loading
Loading
Loading
+67 −8
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@

#include <linux/compat.h>
#include "compat_qseecom.h"
#include <linux/kthread.h>

#define QSEECOM_DEV			"qseecom"
#define QSEOS_VERSION_14		0x14
@@ -140,6 +141,11 @@ enum qseecom_ce_hw_instance {
	CLK_INVALID,
};

enum qseecom_listener_unregister_kthread_state {
	LSNR_UNREG_KT_SLEEP = 0,
	LSNR_UNREG_KT_WAKEUP,
};

static struct class *driver_class;
static dev_t qseecom_device_no;

@@ -298,6 +304,9 @@ struct qseecom_control {

	struct list_head  unregister_lsnr_pending_list_head;
	wait_queue_head_t register_lsnr_pending_wq;
	struct task_struct *unregister_lsnr_kthread_task;
	wait_queue_head_t unregister_lsnr_kthread_wq;
	atomic_t unregister_lsnr_kthread_state;
};

struct qseecom_sec_buf_fd_info {
@@ -1149,8 +1158,14 @@ static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc,

	resp.result = QSEOS_RESULT_INCOMPLETE;

	mutex_unlock(&listener_access_lock);
	mutex_lock(&app_access_lock);
	__qseecom_reentrancy_check_if_no_app_blocked(
				TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID);
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len,
					 &resp, sizeof(resp));
	mutex_unlock(&app_access_lock);
	mutex_lock(&listener_access_lock);
	if (ret) {
		pr_err("qseecom_scm_call failed with err: %d\n", ret);
		return -EINVAL;
@@ -1246,8 +1261,14 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data,
	req.listener_id = data->listener.id;
	resp.result = QSEOS_RESULT_INCOMPLETE;

	mutex_unlock(&listener_access_lock);
	mutex_lock(&app_access_lock);
	__qseecom_reentrancy_check_if_no_app_blocked(
				TZ_OS_DEREGISTER_LISTENER_ID);
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
					sizeof(req), &resp, sizeof(resp));
	mutex_unlock(&app_access_lock);
	mutex_lock(&listener_access_lock);
	if (ret) {
		pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
				ret, data->listener.id);
@@ -1263,9 +1284,6 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data,
		goto exit;
	}

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

	while (atomic_read(&data->ioctl_count) > 1) {
		if (wait_event_freezable(data->abort_wq,
				atomic_read(&data->ioctl_count) <= 1)) {
@@ -1304,6 +1322,10 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
	ptr_svc->abort = 1;
	wake_up_interruptible_all(&qseecom.send_resp_wq);

	/* stop listener thread waiting for listener request */
	data->abort = 1;
	wake_up_all(&ptr_svc->rcv_req_wq);

	/* return directly if pending*/
	if (ptr_svc->unregister_pending)
		return 0;
@@ -1361,6 +1383,30 @@ static void __qseecom_processing_pending_lsnr_unregister(void)
	wake_up_interruptible(&qseecom.register_lsnr_pending_wq);
}

static void __wakeup_unregister_listener_kthread(void)
{
	atomic_set(&qseecom.unregister_lsnr_kthread_state,
				LSNR_UNREG_KT_WAKEUP);
	wake_up_interruptible(&qseecom.unregister_lsnr_kthread_wq);
}

static int __qseecom_unregister_listener_kthread_func(void *data)
{
	while (!kthread_should_stop()) {
		wait_event_freezable(
			qseecom.unregister_lsnr_kthread_wq,
			atomic_read(&qseecom.unregister_lsnr_kthread_state)
				== LSNR_UNREG_KT_WAKEUP);
		pr_debug("kthread to unregister listener is called %d\n",
			atomic_read(&qseecom.unregister_lsnr_kthread_state));
		__qseecom_processing_pending_lsnr_unregister();
		atomic_set(&qseecom.unregister_lsnr_kthread_state,
				LSNR_UNREG_KT_SLEEP);
	}
	pr_warn("kthread to unregister listener stopped\n");
	return 0;
}

static int __qseecom_set_msm_bus_request(uint32_t mode)
{
	int ret = 0;
@@ -3297,7 +3343,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
		pr_err("cache operation failed %d\n", ret2);
		return ret2;
	}
	__qseecom_processing_pending_lsnr_unregister();
	return ret;
}

@@ -4515,7 +4560,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
	uint32_t fw_size, app_arch;
	uint32_t app_id = 0;

	__qseecom_processing_pending_lsnr_unregister();
	__wakeup_unregister_listener_kthread();

	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
		pr_err("Not allowed to be called in %d state\n",
@@ -4689,7 +4734,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle)
	unsigned long flags = 0;
	bool found_handle = false;

	__qseecom_processing_pending_lsnr_unregister();
	__wakeup_unregister_listener_kthread();

	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
		pr_err("Not allowed to be called in %d state\n",
@@ -4739,7 +4784,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
	struct qseecom_dev_handle *data;
	bool perf_enabled = false;

	__qseecom_processing_pending_lsnr_unregister();
	__wakeup_unregister_listener_kthread();

	if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
		pr_err("Not allowed to be called in %d state\n",
@@ -7057,7 +7102,7 @@ static inline long qseecom_ioctl(struct file *file,
		cmd != QSEECOM_IOCTL_SEND_RESP_REQ &&
		cmd != QSEECOM_IOCTL_SEND_MODFD_RESP &&
		cmd != QSEECOM_IOCTL_SEND_MODFD_RESP_64)
		__qseecom_processing_pending_lsnr_unregister();
		__wakeup_unregister_listener_kthread();

	switch (cmd) {
	case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
@@ -8657,6 +8702,7 @@ static int qseecom_probe(struct platform_device *pdev)
	spin_lock_init(&qseecom.registered_kclient_list_lock);
	init_waitqueue_head(&qseecom.send_resp_wq);
	init_waitqueue_head(&qseecom.register_lsnr_pending_wq);
	init_waitqueue_head(&qseecom.unregister_lsnr_kthread_wq);
	qseecom.send_resp_flag = 0;

	qseecom.qsee_version = QSEEE_VERSION_00;
@@ -8857,6 +8903,17 @@ static int qseecom_probe(struct platform_device *pdev)
	if (!qseecom.qsee_perf_client)
		pr_err("Unable to register bus client\n");

	/*create a kthread to process pending listener unregister task */
	qseecom.unregister_lsnr_kthread_task = kthread_run(
			__qseecom_unregister_listener_kthread_func,
			NULL, "qseecom-unreg-lsnr");
	if (IS_ERR(qseecom.unregister_lsnr_kthread_task)) {
		pr_err("failed to create kthread to unregister listener\n");
		rc = -EINVAL;
		goto exit_deinit_clock;
	}
	atomic_set(&qseecom.unregister_lsnr_kthread_state,
					LSNR_UNREG_KT_SLEEP);
	atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY);
	return 0;

@@ -8973,6 +9030,8 @@ static int qseecom_remove(struct platform_device *pdev)

	ion_client_destroy(qseecom.ion_clnt);

	kthread_stop(qseecom.unregister_lsnr_kthread_task);

	cdev_del(&qseecom.cdev);

	device_destroy(driver_class, qseecom_device_no);