فهرست منبع

mm-drivers: hw_fence: update new APIs for synx compat support

Add new APIs to receive params client-id and handles of hw fences
to manage synx compat support.

Change-Id: I5dae0845f8eb2c6c05cc2605d8fc93935c780901
Signed-off-by: Grace An <[email protected]>
Grace An 2 سال پیش
والد
کامیت
66c1c4f019

+ 5 - 3
hw_fence/include/hw_fence_drv_priv.h

@@ -422,11 +422,13 @@ int hw_fence_create(struct hw_fence_driver_data *drv_data,
 int hw_fence_destroy(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
 	u64 context, u64 seqno);
+int hw_fence_destroy_with_hash(struct hw_fence_driver_data *drv_data,
+	struct msm_hw_fence_client *hw_fence_client, u64 hash);
 int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
-	struct dma_fence_array *array);
+	struct dma_fence_array *array, u64 *hash_join_fence);
 int hw_fence_process_fence(struct hw_fence_driver_data *drv_data,
-	struct msm_hw_fence_client *hw_fence_client, struct dma_fence *fence);
+	struct msm_hw_fence_client *hw_fence_client, struct dma_fence *fence, u64 *hash);
 int hw_fence_update_queue(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client, u64 ctxt_id, u64 seqno, u64 hash,
 	u64 flags, u32 error, int queue_type);
@@ -435,7 +437,7 @@ int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
 	struct msm_hw_fence_queue_payload *payload, int queue_type);
 int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
 	struct dma_fence *fence, struct msm_hw_fence_client *hw_fence_client, u64 context,
-	u64 seqno);
+	u64 seqno, u64 *hash);
 struct msm_hw_fence *msm_hw_fence_find(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
 	u64 context, u64 seqno, u64 *hash);

+ 3 - 2
hw_fence/src/hw_fence_drv_debug.c

@@ -345,7 +345,7 @@ static ssize_t hw_fence_dbg_tx_and_signal_clients_wr(struct file *file,
 		/**********************************************/
 		/* use same context and seqno that src client used to create fence */
 		ret = hw_fence_register_wait_client(drv_data, NULL, hw_fence_client_dst, context,
-			seqno);
+			seqno, &hash);
 		if (ret) {
 			HWFNC_ERR("failed to register for wait\n");
 			return -EINVAL;
@@ -861,7 +861,8 @@ static ssize_t hw_fence_dbg_create_join_fence(struct file *file,
 
 	/* wait on the fence array */
 	fence_array_fence = &fence_array->base;
-	msm_hw_fence_wait_update(client_info_dst->client_handle, &fence_array_fence, 1, 1);
+	msm_hw_fence_wait_update_v2(client_info_dst->client_handle, &fence_array_fence, NULL, NULL,
+		1, 1);
 
 	signal_id = dbg_out_clients_signal_map_no_dpu[client_id_src].ipc_signal_id;
 	if (signal_id < 0) {

+ 44 - 13
hw_fence/src/hw_fence_drv_priv.c

@@ -982,6 +982,37 @@ int hw_fence_destroy(struct hw_fence_driver_data *drv_data,
 	return ret;
 }
 
+int hw_fence_destroy_with_hash(struct hw_fence_driver_data *drv_data,
+	struct msm_hw_fence_client *hw_fence_client, u64 hash)
+{
+	u32 client_id = hw_fence_client->client_id;
+	struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
+	struct msm_hw_fence *hw_fence = NULL;
+	int ret = 0;
+
+	hw_fence = _get_hw_fence(drv_data->hw_fence_table_entries, hw_fences_tbl, hash);
+	if (!hw_fence) {
+		HWFNC_ERR("bad hw fence hash:%llu client:%lu\n", hash, client_id);
+		return -EINVAL;
+	}
+
+	if (hw_fence->fence_allocator != client_id) {
+		HWFNC_ERR("client:%lu cannot destroy fence hash:%llu fence_allocator:%lu\n",
+			client_id, hash, hw_fence->fence_allocator);
+		return -EINVAL;
+	}
+
+	/* remove hw fence from table*/
+	if (_hw_fence_cleanup(drv_data, hw_fences_tbl, client_id, hw_fence->ctx_id,
+			hw_fence->seq_id)) {
+		HWFNC_ERR("Fail destroying fence client:%lu ctx:%llu seqno:%llu hash:%llu\n",
+			client_id, hw_fence->ctx_id, hw_fence->seq_id, hash);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static struct msm_hw_fence *_hw_fence_process_join_fence(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
 	struct dma_fence_array *array, u64 *hash, bool create)
@@ -1119,13 +1150,14 @@ static void _cleanup_join_and_child_fences(struct hw_fence_driver_data *drv_data
 }
 
 int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
-	struct msm_hw_fence_client *hw_fence_client, struct dma_fence_array *array)
+	struct msm_hw_fence_client *hw_fence_client, struct dma_fence_array *array,
+	u64 *hash_join_fence)
 {
 	struct msm_hw_fence *join_fence;
 	struct msm_hw_fence *hw_fence_child;
 	struct dma_fence *child_fence;
 	bool signal_join_fence = false;
-	u64 hash_join_fence, hash;
+	u64 hash;
 	int i, ret = 0;
 
 	/*
@@ -1134,7 +1166,7 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 	 * join_fence->pending_child_count = array->num_fences
 	 */
 	join_fence = _hw_fence_process_join_fence(drv_data, hw_fence_client, array,
-		&hash_join_fence, true);
+		hash_join_fence, true);
 	if (!join_fence) {
 		HWFNC_ERR("cannot alloc hw fence for join fence array\n");
 		return -EINVAL;
@@ -1208,7 +1240,7 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 			}
 
 			hw_fence_child->parent_list[hw_fence_child->parents_cnt - 1] =
-				hash_join_fence;
+				*hash_join_fence;
 
 			/* update memory for the table update */
 			wmb();
@@ -1220,7 +1252,7 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 	if (signal_join_fence) {
 
 		/* signal the join hw fence */
-		_fence_ctl_signal(drv_data, hw_fence_client, join_fence, hash_join_fence, 0, 0);
+		_fence_ctl_signal(drv_data, hw_fence_client, join_fence, *hash_join_fence, 0, 0);
 		set_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &array->base.flags);
 
 		/*
@@ -1228,7 +1260,7 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 		 * we can delete it now. This can happen when all the fences that
 		 * are part of the join-fence are already signaled.
 		 */
-		_hw_fence_process_join_fence(drv_data, hw_fence_client, array, &hash_join_fence,
+		_hw_fence_process_join_fence(drv_data, hw_fence_client, array, hash_join_fence,
 			false);
 	}
 
@@ -1236,20 +1268,19 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
 
 error_array:
 	_cleanup_join_and_child_fences(drv_data, hw_fence_client, i, array, join_fence,
-		hash_join_fence);
+		*hash_join_fence);
 
 	return -EINVAL;
 }
 
 int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
 		struct dma_fence *fence, struct msm_hw_fence_client *hw_fence_client, u64 context,
-		u64 seqno)
+		u64 seqno, u64 *hash)
 {
 	struct msm_hw_fence *hw_fence;
-	u64 hash;
 
 	/* find the hw fence within the table */
-	hw_fence = msm_hw_fence_find(drv_data, hw_fence_client, context, seqno, &hash);
+	hw_fence = msm_hw_fence_find(drv_data, hw_fence_client, context, seqno, hash);
 	if (!hw_fence) {
 		HWFNC_ERR("Cannot find fence!\n");
 		return -EINVAL;
@@ -1271,7 +1302,7 @@ int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
 	if (hw_fence->flags & MSM_HW_FENCE_FLAG_SIGNAL) {
 		if (fence != NULL)
 			set_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
-		_fence_ctl_signal(drv_data, hw_fence_client, hw_fence, hash, 0, 0);
+		_fence_ctl_signal(drv_data, hw_fence_client, hw_fence, *hash, 0, 0);
 	}
 
 	return 0;
@@ -1279,7 +1310,7 @@ int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
 
 int hw_fence_process_fence(struct hw_fence_driver_data *drv_data,
 	struct msm_hw_fence_client *hw_fence_client,
-	struct dma_fence *fence)
+	struct dma_fence *fence, u64 *hash)
 {
 	int ret = 0;
 
@@ -1294,7 +1325,7 @@ int hw_fence_process_fence(struct hw_fence_driver_data *drv_data,
 	}
 
 	ret = hw_fence_register_wait_client(drv_data, fence, hw_fence_client, fence->context,
-		fence->seqno);
+		fence->seqno, hash);
 	if (ret)
 		HWFNC_ERR("Error registering for wait client:%d\n", hw_fence_client->client_id);
 

+ 1 - 1
hw_fence/src/hw_fence_ioctl.c

@@ -536,7 +536,7 @@ static long hw_sync_ioctl_reg_for_wait(struct hw_sync_obj *obj, unsigned long ar
 		return -EINVAL;
 	}
 
-	ret = msm_hw_fence_wait_update(obj->client_handle, &fence, num_fences, 1);
+	ret = msm_hw_fence_wait_update_v2(obj->client_handle, &fence, NULL, NULL, num_fences, 1);
 
 	/* Decrement the refcount that hw_sync_get_fence increments */
 	dma_fence_put(fence);

+ 64 - 6
hw_fence/src/msm_hw_fence.c

@@ -238,8 +238,41 @@ int msm_hw_fence_destroy(void *client_handle,
 }
 EXPORT_SYMBOL(msm_hw_fence_destroy);
 
-int msm_hw_fence_wait_update(void *client_handle,
-	struct dma_fence **fence_list, u32 num_fences, bool create)
+int msm_hw_fence_destroy_with_handle(void *client_handle, u64 handle)
+{
+	struct msm_hw_fence_client *hw_fence_client;
+	int ret;
+
+	if (IS_ERR_OR_NULL(client_handle)) {
+		HWFNC_ERR("Invalid data\n");
+		return -EINVAL;
+	}
+	hw_fence_client = (struct msm_hw_fence_client *)client_handle;
+
+	if (hw_fence_client->client_id >= HW_FENCE_CLIENT_MAX) {
+		HWFNC_ERR("Invalid client_id:%d\n", hw_fence_client->client_id);
+		return -EINVAL;
+	}
+
+	HWFNC_DBG_H("+\n");
+
+	/* Destroy the HW Fence, i.e. remove entry in the Global Table for the Fence */
+	ret = hw_fence_destroy_with_hash(hw_fence_drv_data, hw_fence_client, handle);
+	if (ret) {
+		HWFNC_ERR("Error destroying the HW fence handle:%llu client_id:%d\n", handle,
+			hw_fence_client->client_id);
+		return ret;
+	}
+
+	HWFNC_DBG_H("-\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_hw_fence_destroy_with_handle);
+
+int msm_hw_fence_wait_update_v2(void *client_handle,
+	struct dma_fence **fence_list, u64 *handles, u64 *client_data_list, u32 num_fences,
+	bool create)
 {
 	struct msm_hw_fence_client *hw_fence_client;
 	struct dma_fence_array *array;
@@ -262,30 +295,43 @@ int msm_hw_fence_wait_update(void *client_handle,
 	/* Process all the list of fences */
 	for (i = 0; i < num_fences; i++) {
 		struct dma_fence *fence = fence_list[i];
+		u64 hash;
 
 		/* Process a Fence-Array */
 		array = to_dma_fence_array(fence);
 		if (array) {
 			ret = hw_fence_process_fence_array(hw_fence_drv_data, hw_fence_client,
-				array);
+				array, &hash);
 			if (ret) {
-				HWFNC_ERR("Failed to create FenceArray\n");
+				HWFNC_ERR("Failed to process FenceArray\n");
 				return ret;
 			}
 		} else {
 			/* Process individual Fence */
-			ret = hw_fence_process_fence(hw_fence_drv_data, hw_fence_client, fence);
+			ret = hw_fence_process_fence(hw_fence_drv_data, hw_fence_client, fence,
+				&hash);
 			if (ret) {
-				HWFNC_ERR("Failed to create Fence\n");
+				HWFNC_ERR("Failed to process Fence\n");
 				return ret;
 			}
 		}
+
+		if (handles)
+			handles[i] = hash;
 	}
 
 	HWFNC_DBG_H("-\n");
 
 	return 0;
 }
+EXPORT_SYMBOL(msm_hw_fence_wait_update_v2);
+
+int msm_hw_fence_wait_update(void *client_handle,
+	struct dma_fence **fence_list, u32 num_fences, bool create)
+{
+	return msm_hw_fence_wait_update_v2(client_handle, fence_list, NULL, NULL, num_fences,
+		create);
+}
 EXPORT_SYMBOL(msm_hw_fence_wait_update);
 
 int msm_hw_fence_reset_client(void *client_handle, u32 reset_flags)
@@ -316,6 +362,18 @@ int msm_hw_fence_reset_client(void *client_handle, u32 reset_flags)
 }
 EXPORT_SYMBOL(msm_hw_fence_reset_client);
 
+int msm_hw_fence_reset_client_by_id(enum hw_fence_client_id client_id, u32 reset_flags)
+{
+	if (client_id >= HW_FENCE_CLIENT_MAX) {
+		HWFNC_ERR("Invalid client_id:%d\n", client_id);
+		return -EINVAL;
+	}
+
+	return msm_hw_fence_reset_client(hw_fence_drv_data->clients[client_id],
+		reset_flags);
+}
+EXPORT_SYMBOL(msm_hw_fence_reset_client_by_id);
+
 int msm_hw_fence_update_txq(void *client_handle, u64 handle, u64 flags, u32 error)
 {
 	struct msm_hw_fence_client *hw_fence_client;