Переглянути джерело

Merge 17a1e87fc9399e92d0647a15aa063334c643a018 on remote branch

Change-Id: I263c651a37435f8d70b3c205d04e0a6edbefdd74
Linux Build Service Account 2 роки тому
батько
коміт
6df11978f4

+ 1 - 0
crypto-qti/qce.h

@@ -218,4 +218,5 @@ void qce_clear_driver_stats(void *handle);
 void qce_dump_req(void *handle);
 void qce_get_crypto_status(void *handle, struct qce_error *error);
 int qce_manage_timeout(void *handle, int req_info);
+int qce_set_irqs(void *handle, bool enable);
 #endif /* __CRYPTO_MSM_QCE_H */

+ 17 - 2
crypto-qti/qce50.c

@@ -2343,6 +2343,20 @@ static int _qce_unlock_other_pipes(struct qce_device *pce_dev, int req_info)
 	return rc;
 }
 
+static int qce_sps_set_irqs(struct qce_device *pce_dev, bool enable)
+{
+	if (enable)
+		return sps_bam_enable_irqs(pce_dev->ce_bam_info.bam_handle);
+	else
+		return sps_bam_disable_irqs(pce_dev->ce_bam_info.bam_handle);
+}
+
+int qce_set_irqs(void *handle, bool enable)
+{
+	return qce_sps_set_irqs(handle, enable);
+}
+EXPORT_SYMBOL(qce_set_irqs);
+
 static inline void qce_free_req_info(struct qce_device *pce_dev, int req_info,
 		bool is_complete);
 
@@ -3558,7 +3572,7 @@ static void _sps_producer_callback(struct sps_event_notify *notify)
 		preq_info->xfer_type == QCE_XFER_AEAD) &&
 			pce_sps_data->producer_state == QCE_PIPE_STATE_IDLE) {
 		pce_sps_data->producer_state = QCE_PIPE_STATE_COMP;
-		if (!is_offload_op(op)) {
+		if (!is_offload_op(op) && (op < QCE_OFFLOAD_OPER_LAST)) {
 			pce_sps_data->out_transfer.iovec_count = 0;
 			_qce_sps_add_data(GET_PHYS_ADDR(
 					pce_sps_data->result_dump),
@@ -5361,8 +5375,9 @@ static int _qce_resume(void *handle)
 	struct sps_connect *sps_connect_info;
 	int rc, i;
 
+	rc = -ENODEV;
 	if (handle == NULL)
-		return -ENODEV;
+		return rc;
 
 	for (i = 0; i < QCE_OFFLOAD_OPER_LAST; i++) {
 		if (i == QCE_OFFLOAD_NONE && !(pce_dev->kernel_pipes_support))

+ 53 - 8
crypto-qti/qcedev.c

@@ -180,16 +180,31 @@ static void qcedev_ce_high_bw_req(struct qcedev_control *podev,
 {
 	int ret = 0;
 
+	if(podev == NULL) return;
+
 	mutex_lock(&qcedev_sent_bw_req);
 	if (high_bw_req) {
 		if (podev->high_bw_req_count == 0) {
 			ret = qcedev_control_clocks(podev, true);
 			if (ret)
 				goto exit_unlock_mutex;
+			ret = qce_set_irqs(podev->qce, true);
+			if (ret) {
+				pr_err("%s: could not enable bam irqs, ret = %d",
+						__func__, ret);
+				qcedev_control_clocks(podev, false);
+				goto exit_unlock_mutex;
+			}
 		}
 		podev->high_bw_req_count++;
 	} else {
 		if (podev->high_bw_req_count == 1) {
+			ret = qce_set_irqs(podev->qce, false);
+			if (ret) {
+				pr_err("%s: could not disable bam irqs, ret = %d",
+						__func__, ret);
+				goto exit_unlock_mutex;
+			}
 			ret = qcedev_control_clocks(podev, false);
 			if (ret)
 				goto exit_unlock_mutex;
@@ -295,7 +310,9 @@ static int qcedev_release(struct inode *inode, struct file *file)
 					__func__, podev);
 	}
 
-	qcedev_ce_high_bw_req(podev, false);
+	if (podev)
+		qcedev_ce_high_bw_req(podev, false);
+
 	if (qcedev_unmap_all_buffers(handle))
 		pr_err("%s: failed to unmap all ion buffers\n", __func__);
 
@@ -315,8 +332,9 @@ static void req_done(unsigned long data)
 	areq = podev->active_command;
 	podev->active_command = NULL;
 
-	if (areq && !areq->timed_out) {
-		complete(&areq->complete);
+	if (areq) {
+		if (!areq->timed_out)
+			complete(&areq->complete);
 		areq->state = QCEDEV_REQ_DONE;
 	}
 
@@ -713,6 +731,7 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
 	int wait = MAX_CRYPTO_WAIT_TIME;
 	struct qcedev_async_req *new_req = NULL;
 	int retries = 0;
+	int req_wait = MAX_REQUEST_TIME;
 
 	qcedev_areq->err = 0;
 	podev = handle->cntl;
@@ -749,12 +768,16 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
 			list_add_tail(&qcedev_areq->list,
 					&podev->ready_commands);
 			qcedev_areq->state = QCEDEV_REQ_WAITING;
-			if (wait_event_interruptible_lock_irq_timeout(
+			req_wait = wait_event_interruptible_lock_irq_timeout(
 				qcedev_areq->wait_q,
 				(qcedev_areq->state == QCEDEV_REQ_CURRENT),
 				podev->lock,
-				msecs_to_jiffies(MAX_REQUEST_TIME)) == 0) {
-				pr_err("%s: request timed out\n", __func__);
+				msecs_to_jiffies(MAX_REQUEST_TIME));
+			if ((req_wait == 0) || (req_wait == -ERESTARTSYS)) {
+				pr_err("%s: request timed out, req_wait = %d\n",
+						__func__, req_wait);
+				list_del(&qcedev_areq->list);
+				podev->active_command = NULL;
 				spin_unlock_irqrestore(&podev->lock, flags);
 				return qcedev_areq->err;
 			}
@@ -812,7 +835,7 @@ static int submit_req(struct qcedev_async_req *qcedev_areq,
 			pr_err("%s: error during manage timeout", __func__);
 
 		spin_unlock_irqrestore(&podev->lock, flags);
-		tasklet_schedule(&podev->done_tasklet);
+		req_done((unsigned long) podev);
 		if (qcedev_areq->offload_cipher_op_req.err !=
 						QCEDEV_OFFLOAD_NO_ERROR)
 			return 0;
@@ -1733,6 +1756,8 @@ static int qcedev_smmu_ablk_offload_cipher(struct qcedev_async_req *areq,
 		}
 	}
 exit:
+	areq->cipher_req.creq.src = NULL;
+	areq->cipher_req.creq.dst = NULL;
 	return err;
 }
 
@@ -2560,13 +2585,21 @@ static int qcedev_probe_device(struct platform_device *pdev)
 		rc = -ENODEV;
 		goto exit_scale_busbandwidth;
 	}
+	podev->qce = handle;
+
+	rc = qce_set_irqs(podev->qce, false);
+	if (rc) {
+		pr_err("%s: could not disable bam irqs, ret = %d",
+				__func__, rc);
+		goto exit_scale_busbandwidth;
+	}
+
 	rc = icc_set_bw(podev->icc_path, 0, 0);
 	if (rc) {
 		pr_err("%s Unable to set to low bandwidth\n", __func__);
 		goto exit_qce_close;
 	}
 
-	podev->qce = handle;
 	podev->pdev = pdev;
 	platform_set_drvdata(pdev, podev);
 
@@ -2681,6 +2714,12 @@ static int qcedev_suspend(struct platform_device *pdev, pm_message_t state)
 
 	mutex_lock(&qcedev_sent_bw_req);
 	if (podev->high_bw_req_count) {
+		ret = qce_set_irqs(podev->qce, false);
+		if (ret) {
+			pr_err("%s: could not disable bam irqs, ret = %d",
+					__func__, ret);
+			goto suspend_exit;
+		}
 		ret = qcedev_control_clocks(podev, false);
 		if (ret)
 			goto suspend_exit;
@@ -2706,6 +2745,12 @@ static int qcedev_resume(struct platform_device *pdev)
 		ret = qcedev_control_clocks(podev, true);
 		if (ret)
 			goto resume_exit;
+		ret = qce_set_irqs(podev->qce, true);
+		if (ret) {
+			pr_err("%s: could not enable bam irqs, ret = %d",
+					__func__, ret);
+			qcedev_control_clocks(podev, false);
+		}
 	}
 
 resume_exit:

+ 30 - 4
include/linux/IClientEnv.h

@@ -11,8 +11,10 @@
 #define IClientEnv_OP_registerWithWhitelist 3
 #define IClientEnv_OP_notifyDomainChange 4
 #define IClientEnv_OP_registerWithCredentials 5
-#define IClientEnv_OP_accept 6
-#define IClientEnv_OP_adciShutdown 7
+#define IClientEnv_OP_loadCmnlibFromBuffer 6
+#define IClientEnv_OP_configTaRegion 7
+#define IClientEnv_OP_adciAccept 8
+#define IClientEnv_OP_adciShutdown 9
 
 #include "smcinvoke_object.h"
 
@@ -121,9 +123,33 @@ IClientEnv_registerWithCredentials(struct Object self, struct Object
 }
 
 static inline int32_t
-IClientEnv_accept(struct Object self)
+IClientEnv_loadCmnlibFromBuffer(struct Object self, const void *cmnlibElf_ptr, size_t cmnlibElf_len)
 {
-	return Object_invoke(self, IClientEnv_OP_accept, 0, 0);
+  union ObjectArg a[1]={{{0,0}}};
+  a[0].bi = (struct ObjectBufIn) { cmnlibElf_ptr, cmnlibElf_len * 1 };
+
+  return Object_invoke(self, IClientEnv_OP_loadCmnlibFromBuffer, a, ObjectCounts_pack(1, 0, 0, 0));
+}
+
+static inline int32_t
+IClientEnv_configTaRegion(struct Object self, uint64_t appRgnAddr_val, uint32_t appRgnSize_val)
+{
+  union ObjectArg a[1]={{{0,0}}};
+  struct {
+    uint64_t m_appRgnAddr;
+    uint32_t m_appRgnSize;
+  } i;
+  a[0].b = (struct ObjectBuf) { &i, 12 };
+  i.m_appRgnAddr = appRgnAddr_val;
+  i.m_appRgnSize = appRgnSize_val;
+
+  return Object_invoke(self, IClientEnv_OP_configTaRegion, a, ObjectCounts_pack(1, 0, 0, 0));
+}
+
+static inline int32_t
+IClientEnv_adciAccept(struct Object self)
+{
+	return Object_invoke(self, IClientEnv_OP_adciAccept, 0, 0);
 }
 
 static inline int32_t

+ 2 - 0
include/linux/smcinvoke.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #ifndef _UAPI_SMCINVOKE_H_
 #define _UAPI_SMCINVOKE_H_
@@ -9,6 +10,7 @@
 #include <linux/ioctl.h>
 
 #define SMCINVOKE_USERSPACE_OBJ_NULL	-1
+#define DEFAULT_CB_OBJ_THREAD_CNT	4
 
 struct smcinvoke_buf {
 	__u64 addr;

+ 2 - 1
include/linux/smcinvoke_object.h

@@ -184,7 +184,8 @@ static inline void Object_replace(struct Object *loc, struct Object objNew)
 }
 
 #define Object_ASSIGN_NULL(loc)  Object_replace(&(loc), Object_NULL)
-#define SMCINVOKE_INTERFACE_MAX_RETRY		5
+#define SMCINVOKE_INTERFACE_MAX_RETRY       5
+#define SMCINVOKE_INTERFACE_BUSY_WAIT_MS    5
 
 int smcinvoke_release_from_kernel_client(int fd);
 

+ 51 - 11
smcinvoke/smcinvoke.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #define pr_fmt(fmt) "smcinvoke: %s: " fmt, __func__
@@ -26,6 +26,7 @@
 #include <linux/of_platform.h>
 #include <linux/firmware.h>
 #include <linux/qcom_scm.h>
+#include <linux/freezer.h>
 #include <asm/cacheflush.h>
 #include <soc/qcom/qseecomi.h>
 #include <linux/qtee_shmbridge.h>
@@ -138,6 +139,8 @@
 #define TZHANDLE_GET_SERVER(h) ((uint16_t)((h) & 0xFFFF))
 #define TZHANDLE_GET_OBJID(h) (((h) >> 16) & 0x7FFF)
 #define TZHANDLE_MAKE_LOCAL(s, o) (((0x8000 | (o)) << 16) | s)
+#define SET_BIT(s,b) (s | (1 << b))
+#define UNSET_BIT(s,b) (s & (~ (1 << b)))
 
 #define TZHANDLE_IS_NULL(h) ((h) == SMCINVOKE_TZ_OBJ_NULL)
 #define TZHANDLE_IS_LOCAL(h) ((h) & 0x80000000)
@@ -304,6 +307,7 @@ struct smcinvoke_server_info {
 	DECLARE_HASHTABLE(responses_table, 4);
 	struct hlist_node hash;
 	struct list_head pending_cbobjs;
+	uint8_t is_server_suspended;
 };
 
 struct smcinvoke_cbobj {
@@ -618,23 +622,25 @@ static void smcinvoke_start_adci_thread(void)
 	ret = get_client_env_object(&adci_clientEnv);
 	if (ret) {
 		pr_err("failed to get clientEnv for ADCI invoke thread. ret = %d\n", ret);
+		/* Marking it Object_NULL in case of failure scenario in order to avoid
+		 * undefined behavior while releasing garbage adci_clientEnv object.
+		 */
 		adci_clientEnv = Object_NULL;
 		goto out;
 	}
 	/* Invoke call to QTEE which should never return if ADCI is supported */
 	do {
-		ret = IClientEnv_accept(adci_clientEnv);
+		ret = IClientEnv_adciAccept(adci_clientEnv);
 		if (ret == OBJECT_ERROR_BUSY) {
 			pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
-			msleep(5);
+			msleep(SMCINVOKE_INTERFACE_BUSY_WAIT_MS);
 		}
 	} while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));
 
 	if (ret == OBJECT_ERROR_INVALID)
 		pr_err("ADCI feature is not supported on this chipsets, ret = %d\n", ret);
-	/* Need to take decesion here if we want to restart the ADCI thread */
 	else
-		pr_err("Received response from QTEE, ret = %d\n", ret);
+		pr_debug("Received response from QTEE, ret = %d\n", ret);
 out:
 	/* Control should reach to this point only if ADCI feature is not supported by QTEE
 	  (or) ADCI thread held in QTEE is released. */
@@ -747,7 +753,7 @@ static void smcinvoke_destroy_kthreads(void)
 			ret = IClientEnv_adciShutdown(adci_clientEnv);
 			if (ret == OBJECT_ERROR_BUSY) {
 				pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
-				msleep(5);
+				msleep(SMCINVOKE_INTERFACE_BUSY_WAIT_MS);
 			}
 		} while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));
 		if(OBJECT_isERROR(ret)) {
@@ -1717,13 +1723,15 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
 					timeout_jiff);
 		}
 		if (ret == 0) {
-			pr_err("CBobj timed out cb-tzhandle:%d, retry:%d, op:%d counts :%d\n",
-					cb_req->hdr.tzhandle, cbobj_retries,
+			if (srvr_info->is_server_suspended == 0) {
+			pr_err("CBobj timed out waiting on cbtxn :%d,cb-tzhandle:%d, retry:%d, op:%d counts :%d\n",
+					cb_txn->txn_id,cb_req->hdr.tzhandle, cbobj_retries,
 					cb_req->hdr.op, cb_req->hdr.counts);
 			pr_err("CBobj %d timedout pid %x,tid %x, srvr state=%d, srvr id:%u\n",
 					cb_req->hdr.tzhandle, current->pid,
 					current->tgid, srvr_info->state,
 					srvr_info->server_id);
+			}
 		} else {
 			/* wait_event returned due to a signal */
 			if (srvr_info->state != SMCINVOKE_SERVER_STATE_DEFUNCT &&
@@ -1733,7 +1741,16 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
 				break;
 			}
 		}
-		cbobj_retries++;
+		/*
+		 * If bit corresponding to any accept thread is set, invoke threads
+		 * should wait infinitely for the accept thread to come back with
+		 * response.
+		 */
+		if (srvr_info->is_server_suspended > 0) {
+			cbobj_retries = 0;
+		} else {
+			cbobj_retries++;
+		}
 	}
 
 out:
@@ -2396,6 +2413,7 @@ static long process_server_req(struct file *filp, unsigned int cmd,
 	hash_init(server_info->reqs_table);
 	hash_init(server_info->responses_table);
 	INIT_LIST_HEAD(&server_info->pending_cbobjs);
+	server_info->is_server_suspended = 0;
 
 	mutex_lock(&g_smcinvoke_lock);
 
@@ -2459,6 +2477,9 @@ static long process_accept_req(struct file *filp, unsigned int cmd,
 	if (server_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT)
 		server_info->state = 0;
 
+	server_info->is_server_suspended = UNSET_BIT(server_info->is_server_suspended,
+				(current->pid)%DEFAULT_CB_OBJ_THREAD_CNT);
+
 	mutex_unlock(&g_smcinvoke_lock);
 
 	/* First check if it has response otherwise wait for req */
@@ -2522,7 +2543,26 @@ start_waiting_for_requests:
 			 * using server_info and would crash. So dont do that.
 			 */
 			mutex_lock(&g_smcinvoke_lock);
-			server_info->state = SMCINVOKE_SERVER_STATE_DEFUNCT;
+
+			if(freezing(current)) {
+				pr_err("Server id :%d interrupted probaby due to suspend, pid:%d",
+					server_info->server_id, current->pid);
+				/*
+				 * Each accept thread is identified by bits ranging from
+				 * 0 to DEFAULT_CBOBJ_THREAD_CNT-1. When an accept thread is
+				 * interrupted by a signal other than SIGUSR1,SIGKILL,SIGTERM,
+				 * set the corresponding bit of accept thread, indicating that
+				 * current accept thread's state to be "suspended"/ or something
+				 * that needs infinite timeout for invoke thread.
+				 */
+				server_info->is_server_suspended =
+						SET_BIT(server_info->is_server_suspended,
+							(current->pid)%DEFAULT_CB_OBJ_THREAD_CNT);
+			} else {
+				pr_err("Setting pid:%d, server id : %d state to defunct",
+						current->pid, server_info->server_id);
+						server_info->state = SMCINVOKE_SERVER_STATE_DEFUNCT;
+			}
 			mutex_unlock(&g_smcinvoke_lock);
 			wake_up_interruptible(&server_info->rsp_wait_q);
 			goto out;
@@ -2622,7 +2662,7 @@ static long process_invoke_req(struct file *filp, unsigned int cmd,
 			tzobj->tzhandle == SMCINVOKE_TZ_ROOT_OBJ &&
 			(req.op == IClientEnv_OP_notifyDomainChange ||
 			req.op == IClientEnv_OP_registerWithCredentials ||
-			req.op == IClientEnv_OP_accept ||
+			req.op == IClientEnv_OP_adciAccept ||
 			req.op == IClientEnv_OP_adciShutdown)) {
 		pr_err("invalid rootenv op\n");
 		return -EINVAL;

+ 1 - 1
smcinvoke/smcinvoke_kernel.c

@@ -312,7 +312,7 @@ int32_t get_client_env_object(struct Object *clientEnvObj)
 			Object_NULL, clientEnvObj);
 		if (ret == OBJECT_ERROR_BUSY) {
 			pr_err("Secure side is busy,will retry after 5 ms, retry_count = %d",retry_count);
-			msleep(5);
+			msleep(SMCINVOKE_INTERFACE_BUSY_WAIT_MS);
 		}
 	} while ((ret == OBJECT_ERROR_BUSY) && (retry_count++ < SMCINVOKE_INTERFACE_MAX_RETRY));