Procházet zdrojové kódy

Merge "mm-drivers: hw_fence: fix edge cases for hwfence ioctls"

qctecmdr před 2 roky
rodič
revize
5827c82e14

+ 2 - 1
hw_fence/src/hw_fence_drv_debug.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/debugfs.h>
@@ -907,6 +907,7 @@ int process_validation_client_loopback(struct hw_fence_driver_data *drv_data,
 
 	if (!drv_data->clients[client_id]) {
 		mutex_unlock(&drv_data->clients_register_lock);
+		HWFNC_ERR("Processing workaround for unregistered val client:%d\n", client_id);
 		return -EINVAL;
 	}
 

+ 6 - 6
hw_fence/src/hw_fence_drv_utils.c

@@ -50,6 +50,12 @@
 #define HW_FENCE_CLIENT_TYPE_MAX_VPU 32
 #define HW_FENCE_CLIENT_TYPE_MAX_IFE 32
 
+/*
+ * Each bit in this mask represents each of the loopback clients supported in
+ * the enum hw_fence_loopback_id
+ */
+#define HW_FENCE_LOOPBACK_CLIENTS_MASK 0x7fff
+
 /**
  * struct hw_fence_client_types - Table describing all supported client types, used to parse
  *                                device-tree properties related to client queue size.
@@ -156,12 +162,6 @@ void global_atomic_store(struct hw_fence_driver_data *drv_data, uint64_t *lock,
 	}
 }
 
-/*
- * Each bit in this mask represents each of the loopback clients supported in
- * the enum hw_fence_loopback_id
- */
-#define HW_FENCE_LOOPBACK_CLIENTS_MASK 0x7f
-
 static inline int _process_dpu_client_loopback(struct hw_fence_driver_data *drv_data,
 	int client_id)
 {

+ 14 - 4
hw_fence/src/hw_fence_ioctl.c

@@ -6,6 +6,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
+#include <linux/ktime.h>
 #include <linux/types.h>
 #include <linux/sync_file.h>
 
@@ -39,6 +40,8 @@
 		.name = #ioctl			\
 	}
 
+#define ktime_compare_safe(A, B) ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0))
+
 /**
  * struct hw_sync_obj - per client hw sync object.
  * @context: context id used to create fences.
@@ -371,7 +374,7 @@ static long hw_sync_ioctl_create_fence_array(struct hw_sync_obj *obj, unsigned l
 		return -EFAULT;
 
 	num_fences = data.num_fences;
-	if (num_fences >= HW_FENCE_ARRAY_SIZE) {
+	if (num_fences > HW_FENCE_ARRAY_SIZE) {
 		HWFNC_ERR("Number of fences: %d is greater than allowed size: %d\n",
 					num_fences, HW_FENCE_ARRAY_SIZE);
 		return -EINVAL;
@@ -559,6 +562,7 @@ static long hw_sync_ioctl_fence_wait(struct hw_sync_obj *obj, unsigned long arg)
 	struct msm_hw_fence_queue_payload payload;
 	struct hw_fence_sync_wait_data data;
 	struct dma_fence *fence;
+	ktime_t cur_ktime, exp_ktime;
 	int fd, ret, read = 1, queue_type = HW_FENCE_RX_QUEUE - 1;  /* rx queue index */
 
 	if (!_is_valid_client(obj))
@@ -582,9 +586,15 @@ static long hw_sync_ioctl_fence_wait(struct hw_sync_obj *obj, unsigned long arg)
 		return -EINVAL;
 	}
 
-	ret = wait_event_timeout(hw_fence_client->wait_queue,
-			atomic_read(&hw_fence_client->val_signal) > 0,
-			msecs_to_jiffies(data.timeout_ms));
+	exp_ktime = ktime_add_ms(ktime_get(), data.timeout_ms);
+	do {
+		ret = wait_event_timeout(hw_fence_client->wait_queue,
+				atomic_read(&hw_fence_client->val_signal) > 0,
+				msecs_to_jiffies(data.timeout_ms));
+		cur_ktime = ktime_get();
+	} while ((atomic_read(&hw_fence_client->val_signal) <= 0) && (ret == 0) &&
+		ktime_compare_safe(exp_ktime, cur_ktime) > 0);
+
 	if (!ret) {
 		HWFNC_ERR("timed out waiting for the client signal %d\n", data.timeout_ms);
 		/* Decrement the refcount that hw_sync_get_fence increments */