Procházet zdrojové kódy

Merge e0d65b7ccae0f61a18dff315691e2c4bbf9e32fa on remote branch

Change-Id: Idbd21e62ecde3012a34f27fc24596e8f50ea895c
Linux Build Service Account před 2 roky
rodič
revize
f2324a7a53

+ 2 - 0
hw_fence/include/hw_fence_drv_priv.h

@@ -473,6 +473,8 @@ int hw_fence_init_controller_signal(struct hw_fence_driver_data *drv_data,
 int hw_fence_init_controller_resources(struct msm_hw_fence_client *hw_fence_client);
 void hw_fence_cleanup_client(struct hw_fence_driver_data *drv_data,
 	 struct msm_hw_fence_client *hw_fence_client);
+void hw_fence_utils_reset_queues(struct hw_fence_driver_data *drv_data,
+	struct msm_hw_fence_client *hw_fence_client);
 int hw_fence_create(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
 	u64 context, u64 seqno, u64 *hash);

+ 43 - 0
hw_fence/src/hw_fence_drv_priv.c

@@ -1430,6 +1430,49 @@ static void _signal_all_wait_clients(struct hw_fence_driver_data *drv_data,
 	}
 }
 
+void hw_fence_utils_reset_queues(struct hw_fence_driver_data *drv_data,
+	struct msm_hw_fence_client *hw_fence_client)
+{
+	struct msm_hw_fence_hfi_queue_header *hfi_header;
+	struct msm_hw_fence_queue *queue;
+	u32 rd_idx, wr_idx, lock_idx;
+
+	queue = &hw_fence_client->queues[HW_FENCE_TX_QUEUE - 1];
+	hfi_header = queue->va_header;
+
+	/* For the client TxQ: set the read-index same as last write that was done by the client */
+	mb(); /* make sure data is ready before read */
+	wr_idx = readl_relaxed(&hfi_header->write_index);
+	writel_relaxed(wr_idx, &hfi_header->read_index);
+	wmb(); /* make sure data is updated after write the index*/
+
+	/* For the client RxQ: set the write-index same as last read done by the client */
+	if (hw_fence_client->update_rxq) {
+		lock_idx = hw_fence_client->client_id - 1;
+
+		if (lock_idx >= drv_data->client_lock_tbl_cnt) {
+			HWFNC_ERR("cannot reset rxq, lock for client id:%d exceed max:%d\n",
+				hw_fence_client->client_id, drv_data->client_lock_tbl_cnt);
+			return;
+		}
+		HWFNC_DBG_Q("Locking client id:%d: idx:%d\n", hw_fence_client->client_id, lock_idx);
+
+		/* lock the client rx queue to update */
+		GLOBAL_ATOMIC_STORE(drv_data, &drv_data->client_lock_tbl[lock_idx], 1);
+
+		queue = &hw_fence_client->queues[HW_FENCE_RX_QUEUE - 1];
+		hfi_header = queue->va_header;
+
+		mb(); /* make sure data is ready before read */
+		rd_idx = readl_relaxed(&hfi_header->read_index);
+		writel_relaxed(rd_idx, &hfi_header->write_index);
+		wmb(); /* make sure data is updated after write the index */
+
+		/* unlock */
+		GLOBAL_ATOMIC_STORE(drv_data, &drv_data->client_lock_tbl[lock_idx], 0);
+	}
+}
+
 int hw_fence_utils_cleanup_fence(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client, struct msm_hw_fence *hw_fence, u64 hash,
 	u32 reset_flags)

+ 13 - 12
hw_fence/src/hw_fence_drv_utils.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of_platform.h>
@@ -8,6 +8,7 @@
 #include <linux/io.h>
 #include <linux/gunyah/gh_rm_drv.h>
 #include <linux/gunyah/gh_dbl.h>
+#include <linux/qcom_scm.h>
 #include <soc/qcom/secure_buffer.h>
 
 #include "hw_fence_drv_priv.h"
@@ -339,18 +340,19 @@ int hw_fence_utils_init_virq(struct hw_fence_driver_data *drv_data)
 static int hw_fence_gunyah_share_mem(struct hw_fence_driver_data *drv_data,
 				gh_vmid_t self, gh_vmid_t peer)
 {
-	u32 src_vmlist[1] = {self};
-	int src_perms[2] = {PERM_READ | PERM_WRITE | PERM_EXEC};
-	int dst_vmlist[2] = {self, peer};
-	int dst_perms[2] = {PERM_READ | PERM_WRITE, PERM_READ | PERM_WRITE};
+	struct qcom_scm_vmperm src_vmlist[] = {{self, PERM_READ | PERM_WRITE | PERM_EXEC}};
+	struct qcom_scm_vmperm dst_vmlist[] = {{self, PERM_READ | PERM_WRITE},
+					       {peer, PERM_READ | PERM_WRITE}};
+	int srcvmids = BIT(src_vmlist[0].vmid);
+	int dstvmids = BIT(dst_vmlist[0].vmid) | BIT(dst_vmlist[1].vmid);
 	struct gh_acl_desc *acl;
 	struct gh_sgl_desc *sgl;
 	int ret;
 
-	ret = hyp_assign_phys(drv_data->res.start, resource_size(&drv_data->res),
-			src_vmlist, 1, dst_vmlist, dst_perms, 2);
+	ret = qcom_scm_assign_mem(drv_data->res.start, resource_size(&drv_data->res), &srcvmids,
+			dst_vmlist, ARRAY_SIZE(dst_vmlist));
 	if (ret) {
-		HWFNC_ERR("%s: hyp_assign_phys failed addr=%x size=%u err=%d\n",
+		HWFNC_ERR("%s: qcom_scm_assign_mem failed addr=%x size=%u err=%d\n",
 			__func__, drv_data->res.start, drv_data->size, ret);
 		return ret;
 	}
@@ -379,9 +381,8 @@ static int hw_fence_gunyah_share_mem(struct hw_fence_driver_data *drv_data,
 		HWFNC_ERR("%s: gh_rm_mem_share failed addr=%x size=%u err=%d\n",
 			__func__, drv_data->res.start, drv_data->size, ret);
 		/* Attempt to give resource back to HLOS */
-		hyp_assign_phys(drv_data->res.start, resource_size(&drv_data->res),
-				dst_vmlist, 2,
-				src_vmlist, src_perms, 1);
+		qcom_scm_assign_mem(drv_data->res.start, resource_size(&drv_data->res),
+				&dstvmids, src_vmlist, ARRAY_SIZE(src_vmlist));
 		ret = -EPROBE_DEFER;
 	}
 
@@ -471,7 +472,7 @@ int hw_fence_utils_alloc_mem(struct hw_fence_driver_data *drv_data)
 		return -EINVAL;
 	}
 
-	drv_data->io_mem_base = devm_ioremap(dev, drv_data->res.start,
+	drv_data->io_mem_base = devm_ioremap_wc(dev, drv_data->res.start,
 		resource_size(&drv_data->res));
 	if (!drv_data->io_mem_base) {
 		HWFNC_ERR("ioremap failed!\n");

+ 26 - 15
hw_fence/src/msm_hw_fence.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -24,6 +24,9 @@ void *msm_hw_fence_register(enum hw_fence_client_id client_id_ext,
 	enum hw_fence_client_id client_id;
 	int ret;
 
+	if (!hw_fence_driver_enable)
+		return ERR_PTR(-ENODEV);
+
 	HWFNC_DBG_H("++ client_id_ext:%d\n", client_id_ext);
 
 	if (IS_ERR_OR_NULL(hw_fence_drv_data) || !hw_fence_drv_data->resources_ready) {
@@ -389,11 +392,13 @@ int msm_hw_fence_reset_client(void *client_handle, u32 reset_flags)
 	hw_fence_client = (struct msm_hw_fence_client *)client_handle;
 	hw_fences_tbl = hw_fence_drv_data->hw_fences_tbl;
 
-	HWFNC_DBG_L("reset fences for client:%d\n", hw_fence_client->client_id);
+	HWFNC_DBG_L("reset fences and queues for client:%d\n", hw_fence_client->client_id);
 	for (i = 0; i < hw_fence_drv_data->hw_fences_tbl_cnt; i++)
 		hw_fence_utils_cleanup_fence(hw_fence_drv_data, hw_fence_client,
 			&hw_fences_tbl[i], i, reset_flags);
 
+	hw_fence_utils_reset_queues(hw_fence_drv_data, hw_fence_client);
+
 	return 0;
 }
 EXPORT_SYMBOL(msm_hw_fence_reset_client);
@@ -500,15 +505,26 @@ static int msm_hw_fence_probe_init(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, hw_fence_drv_data);
 	hw_fence_drv_data->dev = &pdev->dev;
 
-	/* Initialize HW Fence Driver resources */
-	rc = hw_fence_init(hw_fence_drv_data);
-	if (rc)
-		goto error;
-
-	mutex_init(&hw_fence_drv_data->clients_register_lock);
+	if (hw_fence_driver_enable) {
+		/* Initialize HW Fence Driver resources */
+		rc = hw_fence_init(hw_fence_drv_data);
+		if (rc)
+			goto error;
+
+		mutex_init(&hw_fence_drv_data->clients_register_lock);
+
+		/* set ready value so clients can register */
+		hw_fence_drv_data->resources_ready = true;
+	} else {
+		/* Allocate hw fence driver mem pool and share it with HYP */
+		rc = hw_fence_utils_alloc_mem(hw_fence_drv_data);
+		if (rc) {
+			HWFNC_ERR("failed to alloc base memory\n");
+			goto error;
+		}
 
-	/* set ready ealue so clients can register */
-	hw_fence_drv_data->resources_ready = true;
+		HWFNC_DBG_INFO("hw fence driver not enabled\n");
+	}
 
 	HWFNC_DBG_H("-\n");
 
@@ -534,11 +550,6 @@ static int msm_hw_fence_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	if (!hw_fence_driver_enable) {
-		HWFNC_DBG_INFO("hw fence driver not enabled\n");
-		return -EOPNOTSUPP;
-	}
-
 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-hw-fence"))
 		rc = msm_hw_fence_probe_init(pdev);
 	if (rc)