Przeglądaj źródła

mm-drivers: hw_fence: add support for ipe, vpu, and ife clients

Update hw fence driver to support new clients with large number
of possible sub-clients, which can be configured in device-tree.
Add client queues support for ipe, vpu, and ife clients.

Change-Id: I6e274819c1c154af3ea977d1d09e419d86f6fe8e
Signed-off-by: Grace An <[email protected]>
Grace An 2 lat temu
rodzic
commit
368ae72991

+ 1 - 1
hw_fence/include/hw_fence_drv_debug.h

@@ -85,7 +85,7 @@ struct hw_fence_out_clients_map {
  * The index of this struct must match the enum hw_fence_client_id
  */
 static const struct hw_fence_out_clients_map
-			dbg_out_clients_signal_map_no_dpu[HW_FENCE_CLIENT_MAX] = {
+			dbg_out_clients_signal_map_no_dpu[HW_FENCE_CLIENT_ID_VAL6 + 1] = {
 	{HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 0},  /* CTRL_LOOPBACK */
 	{HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0},  /* CTX0 */
 	{HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 2},  /* CTL0 */

+ 14 - 6
hw_fence/include/hw_fence_drv_priv.h

@@ -48,8 +48,8 @@
 #define HW_FENCE_CTRL_QUEUE_PAYLOAD HW_FENCE_CTRL_QUEUE_MAX_PAYLOAD_SIZE
 #define HW_FENCE_CLIENT_QUEUE_PAYLOAD (sizeof(struct msm_hw_fence_queue_payload))
 
-/* Locks area for all the clients */
-#define HW_FENCE_MEM_LOCKS_SIZE (sizeof(u64) * (HW_FENCE_CLIENT_MAX - 1))
+/* Locks area for all clients with RxQ */
+#define HW_FENCE_MEM_LOCKS_SIZE(rxq_clients_num) (sizeof(u64) * rxq_clients_num)
 
 #define HW_FENCE_TX_QUEUE 1
 #define HW_FENCE_RX_QUEUE 2
@@ -165,7 +165,9 @@ enum payload_type {
 
 /**
  * struct msm_hw_fence_client - Structure holding the per-Client allocated resources.
- * @client_id: id of the client
+ * @client_id: internal client_id used within HW fence driver; index into the clients struct
+ * @client_id_ext: external client_id, equal to client_id except for clients with configurable
+ *                 number of sub-clients (e.g. ife clients)
  * @mem_descriptor: hfi header memory descriptor
  * @queues: queues descriptor
  * @ipc_signal_id: id of the signal to be triggered for this client
@@ -178,6 +180,7 @@ enum payload_type {
  */
 struct msm_hw_fence_client {
 	enum hw_fence_client_id client_id;
+	enum hw_fence_client_id client_id_ext;
 	struct msm_hw_fence_mem_addr mem_descriptor;
 	struct msm_hw_fence_queue queues[HW_FENCE_CLIENT_QUEUES];
 	int ipc_signal_id;
@@ -257,6 +260,8 @@ struct hw_fence_client_queue_size_desc {
  * @hw_fence_ctrl_queue_size: size of the ctrl queue for the payload
  * @hw_fence_mem_ctrl_queues_size: total size of ctrl queues, including: header + rxq + txq
  * @hw_fence_client_queue_size: descriptors of client queue properties for each hw fence client
+ * @rxq_clients_num: number of supported hw fence clients with rxq (configured based on device-tree)
+ * @clients_num: number of supported hw fence clients (configured based on device-tree)
  * @hw_fences_tbl: pointer to the hw-fences table
  * @hw_fences_tbl_cnt: number of elements in the hw-fence table
  * @client_lock_tbl: pointer to the per-client locks table
@@ -290,7 +295,7 @@ struct hw_fence_client_queue_size_desc {
  * @ctl_start_size: size of the ctl_start registers of the display hw (platforms with no dpu-ipc)
  * @client_id_mask: bitmask for tracking registered client_ids
  * @clients_register_lock: lock to synchronize clients registration and deregistration
- * @msm_hw_fence_client: table with the handles of the registered clients
+ * @clients: table with the handles of the registered clients; size is equal to clients_num
  * @vm_ready: flag to indicate if vm has been initialized
  * @ipcc_dpu_initialized: flag to indicate if dpu hw is initialized
  */
@@ -307,7 +312,10 @@ struct hw_fence_driver_data {
 	u32 hw_fence_ctrl_queue_size;
 	u32 hw_fence_mem_ctrl_queues_size;
 	/* client queues */
-	struct hw_fence_client_queue_size_desc hw_fence_client_queue_size[HW_FENCE_CLIENT_MAX];
+	struct hw_fence_client_queue_size_desc *hw_fence_client_queue_size;
+	struct hw_fence_client_type_desc *hw_fence_client_types;
+	u32 rxq_clients_num;
+	u32 clients_num;
 
 	/* HW Fences Table VA */
 	struct msm_hw_fence *hw_fences_tbl;
@@ -366,7 +374,7 @@ struct hw_fence_driver_data {
 	struct mutex clients_register_lock;
 
 	/* table with registered client handles */
-	struct msm_hw_fence_client *clients[HW_FENCE_CLIENT_MAX];
+	struct msm_hw_fence_client **clients;
 
 	bool vm_ready;
 #ifdef HW_DPU_IPCC

+ 17 - 0
hw_fence/include/hw_fence_drv_utils.h

@@ -111,4 +111,21 @@ 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);
 
+/**
+ * hw_fence_utils_get_client_id_priv() - Gets the index into clients struct within hw fence driver
+ *                                       from the client_id used externally
+ *
+ * Performs a 1-to-1 mapping for all client IDs less than HW_FENCE_MAX_STATIC_CLIENTS_INDEX,
+ * otherwise consolidates client IDs of clients with configurable number of sub-clients. Fails if
+ * provided with client IDs for such clients when support for those clients is not configured in
+ * device-tree.
+ *
+ * @drv_data: hw fence driver data
+ * @client_id: external client_id to get internal client_id for
+ *
+ * Returns client_id < drv_data->clients_num if success, otherwise returns HW_FENCE_CLIENT_MAX
+ */
+enum hw_fence_client_id hw_fence_utils_get_client_id_priv(struct hw_fence_driver_data *drv_data,
+	enum hw_fence_client_id client_id);
+
 #endif /* __HW_FENCE_DRV_UTILS_H */

+ 19 - 3
hw_fence/src/hw_fence_drv_priv.c

@@ -46,7 +46,7 @@ static int init_hw_fences_queues(struct hw_fence_driver_data *drv_data,
 		payload_size = HW_FENCE_CTRL_QUEUE_PAYLOAD;
 		break;
 	case HW_FENCE_MEM_RESERVE_CLIENT_QUEUE:
-		if (client_id >= HW_FENCE_CLIENT_MAX) {
+		if (client_id >= drv_data->clients_num) {
 			HWFNC_ERR("Invalid client_id: %d\n", client_id);
 			return -EINVAL;
 		}
@@ -563,7 +563,7 @@ int hw_fence_init_controller_signal(struct hw_fence_driver_data *drv_data,
 	 * however, if that is  not the case, any per-client ipcc init to enable the
 	 * signaling, can go here.
 	 */
-	switch (hw_fence_client->client_id) {
+	switch ((int)hw_fence_client->client_id) {
 	case HW_FENCE_CLIENT_ID_CTX0:
 		/* nothing to initialize for gpu client */
 		break;
@@ -596,6 +596,16 @@ int hw_fence_init_controller_signal(struct hw_fence_driver_data *drv_data,
 		}
 #endif /* HW_DPU_IPCC */
 		break;
+	case HW_FENCE_CLIENT_ID_IPE:
+		/* nothing to initialize for IPE client */
+		break;
+	case HW_FENCE_CLIENT_ID_VPU:
+		/* nothing to initialize for VPU client */
+		break;
+	case HW_FENCE_CLIENT_ID_IFE0 ... HW_FENCE_CLIENT_ID_IFE7 +
+			MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT - 1:
+		/* nothing to initialize for IFE clients */
+		break;
 	default:
 		HWFNC_ERR("Unexpected client:%d\n", hw_fence_client->client_id);
 		ret = -EINVAL;
@@ -1397,7 +1407,7 @@ static void _signal_all_wait_clients(struct hw_fence_driver_data *drv_data,
 	u64 client_data = 0;
 
 	/* signal with an error all the waiting clients for this fence */
-	for (wait_client_id = 0; wait_client_id < HW_FENCE_CLIENT_MAX; wait_client_id++) {
+	for (wait_client_id = 0; wait_client_id <= drv_data->rxq_clients_num; wait_client_id++) {
 		if (hw_fence->wait_client_mask & BIT(wait_client_id)) {
 			hw_fence_wait_client = drv_data->clients[wait_client_id];
 			data_id = hw_fence_get_client_data_id(wait_client_id);
@@ -1466,6 +1476,12 @@ enum hw_fence_client_data_id hw_fence_get_client_data_id(enum hw_fence_client_id
 	case HW_FENCE_CLIENT_ID_VAL1:
 		data_id = HW_FENCE_CLIENT_DATA_ID_VAL1;
 		break;
+	case HW_FENCE_CLIENT_ID_IPE:
+		data_id = HW_FENCE_CLIENT_DATA_ID_IPE;
+		break;
+	case HW_FENCE_CLIENT_ID_VPU:
+		data_id = HW_FENCE_CLIENT_DATA_ID_VPU;
+		break;
 	default:
 		data_id = HW_FENCE_MAX_CLIENTS_WITH_DATA;
 		break;

+ 128 - 10
hw_fence/src/hw_fence_drv_utils.c

@@ -21,16 +21,50 @@
  */
 #define MAX_CLIENT_QUEUE_MEM_SIZE 0x100000
 
+/**
+ * HW_FENCE_MAX_CLIENT_TYPE_STATIC:
+ * Total number of client types without configurable number of sub-clients (GFX, DPU, VAL, IPE, VPU)
+ */
+#define HW_FENCE_MAX_CLIENT_TYPE_STATIC 5
+
+/**
+ * HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE:
+ * Maximum number of client types with configurable number of sub-clients (e.g. IFE)
+ */
+#define HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE 8
+
 /**
  * HW_FENCE_MAX_CLIENT_TYPE:
- * Total number of client types (GFX, DPU, VAL)
+ * Total number of client types with and without configurable number of sub-clients
  */
-#define HW_FENCE_MAX_CLIENT_TYPE 3
+#define HW_FENCE_MAX_CLIENT_TYPE (HW_FENCE_MAX_CLIENT_TYPE_STATIC + \
+	HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE)
+
+/**
+ * HW_FENCE_MAX_STATIC_CLIENTS_INDEX:
+ * Maximum number of static clients, i.e. clients without configurable numbers of sub-clients
+ */
+#define HW_FENCE_MAX_STATIC_CLIENTS_INDEX HW_FENCE_CLIENT_ID_IFE0
+
+/**
+ * HW_FENCE_MIN_RXQ_CLIENTS:
+ * Minimum number of static hw fence clients with rxq
+ */
+#define HW_FENCE_MIN_RXQ_CLIENTS HW_FENCE_CLIENT_ID_VAL6
+
+/**
+ * HW_FENCE_MIN_RXQ_CLIENT_TYPE:
+ * Minimum number of static hw fence client types with rxq (GFX, DPU, VAL)
+ */
+#define HW_FENCE_MIN_RXQ_CLIENT_TYPE 3
 
 /* Maximum number of clients for each client type */
 #define HW_FENCE_CLIENT_TYPE_MAX_GPU 1
 #define HW_FENCE_CLIENT_TYPE_MAX_DPU 6
 #define HW_FENCE_CLIENT_TYPE_MAX_VAL 7
+#define HW_FENCE_CLIENT_TYPE_MAX_IPE 1
+#define HW_FENCE_CLIENT_TYPE_MAX_VPU 1
+#define HW_FENCE_CLIENT_TYPE_MAX_IFE 32
 
 /**
  * struct hw_fence_client_type_desc - Structure holding client type properties, including static
@@ -71,7 +105,8 @@ struct hw_fence_client_type_desc {
  * 1. Client types must be in the same order as client_ids within the enum 'hw_fence_client_id'.
  * 2. Each HW Fence client ID must be described by one of the client types in this table.
  * 3. A new client type must set: name, init_id, max_clients_num, clients_num, and queues_num.
- * 4. HW_FENCE_MAX_CLIENT_TYPE must be incremented for new client types.
+ * 4. Either constant HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE or HW_FENCE_MAX_CLIENT_TYPE_STATIC must
+ *    be incremented as appropriate for new client types.
  */
 struct hw_fence_client_type_desc hw_fence_client_types[HW_FENCE_MAX_CLIENT_TYPE] = {
 	{"gpu", HW_FENCE_CLIENT_ID_CTX0, HW_FENCE_CLIENT_TYPE_MAX_GPU, HW_FENCE_CLIENT_TYPE_MAX_GPU,
@@ -80,6 +115,18 @@ struct hw_fence_client_type_desc hw_fence_client_types[HW_FENCE_MAX_CLIENT_TYPE]
 		HW_FENCE_CLIENT_QUEUES, 0, 0},
 	{"val", HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_TYPE_MAX_VAL, HW_FENCE_CLIENT_TYPE_MAX_VAL,
 		HW_FENCE_CLIENT_QUEUES, 0, 0},
+	{"ipe", HW_FENCE_CLIENT_ID_IPE, HW_FENCE_CLIENT_TYPE_MAX_IPE, 0,
+		HW_FENCE_CLIENT_QUEUES, 0, 0},
+	{"vpu", HW_FENCE_CLIENT_ID_VPU, HW_FENCE_CLIENT_TYPE_MAX_VPU, 0,
+		HW_FENCE_CLIENT_QUEUES, 0, 0},
+	{"ife0", HW_FENCE_CLIENT_ID_IFE0, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife1", HW_FENCE_CLIENT_ID_IFE1, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife2", HW_FENCE_CLIENT_ID_IFE2, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife3", HW_FENCE_CLIENT_ID_IFE3, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife4", HW_FENCE_CLIENT_ID_IFE4, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife5", HW_FENCE_CLIENT_ID_IFE5, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife6", HW_FENCE_CLIENT_ID_IFE6, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
+	{"ife7", HW_FENCE_CLIENT_ID_IFE7, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
 };
 
 static void _lock(uint64_t *wait)
@@ -527,15 +574,16 @@ int hw_fence_utils_reserve_mem(struct hw_fence_driver_data *drv_data,
 	case HW_FENCE_MEM_RESERVE_LOCKS_REGION:
 		/* Locks region starts at the end of the ctrl queues */
 		start_offset = drv_data->hw_fence_mem_ctrl_queues_size;
-		*size = HW_FENCE_MEM_LOCKS_SIZE;
+		*size = HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num);
 		break;
 	case HW_FENCE_MEM_RESERVE_TABLE:
 		/* HW Fence table starts at the end of the Locks region */
-		start_offset = drv_data->hw_fence_mem_ctrl_queues_size + HW_FENCE_MEM_LOCKS_SIZE;
+		start_offset = drv_data->hw_fence_mem_ctrl_queues_size +
+			HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num);
 		*size = drv_data->hw_fence_mem_fences_table_size;
 		break;
 	case HW_FENCE_MEM_RESERVE_CLIENT_QUEUE:
-		if (client_id >= HW_FENCE_CLIENT_MAX) {
+		if (client_id >= drv_data->clients_num) {
 			HWFNC_ERR("unexpected client_id:%d\n", client_id);
 			ret = -EINVAL;
 			goto exit;
@@ -641,9 +689,10 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
 	struct hw_fence_client_type_desc *desc;
 	int i, j, ret;
 	u32 start_offset;
+	size_t size;
+	int configurable_clients_num = 0;
 
-	start_offset = PAGE_ALIGN(drv_data->hw_fence_mem_ctrl_queues_size +
-		HW_FENCE_MEM_LOCKS_SIZE + drv_data->hw_fence_mem_fences_table_size);
+	drv_data->rxq_clients_num = HW_FENCE_MIN_RXQ_CLIENTS;
 	for (i = 0; i < HW_FENCE_MAX_CLIENT_TYPE; i++) {
 		desc = &hw_fence_client_types[i];
 		ret = _parse_client_queue_dt_props_indv(drv_data, desc);
@@ -653,12 +702,43 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
 			return ret;
 		}
 
-		/* initialize client queue size desc for each client */
+		if (i >= HW_FENCE_MIN_RXQ_CLIENT_TYPE &&
+				desc->queues_num == HW_FENCE_CLIENT_QUEUES)
+			drv_data->rxq_clients_num += desc->clients_num;
+
+		if (i >= HW_FENCE_MAX_CLIENT_TYPE_STATIC)
+			configurable_clients_num += desc->clients_num;
+	}
+
+	/* store client type descriptors for configurable client indexing logic */
+	drv_data->hw_fence_client_types = hw_fence_client_types;
+
+	/* clients and size desc are allocated for all static clients regardless of device-tree */
+	drv_data->clients_num = HW_FENCE_MAX_STATIC_CLIENTS_INDEX + configurable_clients_num;
+
+	/* allocate memory for client queue size descriptors */
+	size = drv_data->clients_num * sizeof(struct hw_fence_client_queue_size_desc);
+	drv_data->hw_fence_client_queue_size = kzalloc(size, GFP_KERNEL);
+	if (!drv_data->hw_fence_client_queue_size)
+		return -ENOMEM;
+
+	/* initialize client queue size desc for each client */
+	start_offset = PAGE_ALIGN(drv_data->hw_fence_mem_ctrl_queues_size +
+		HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num) +
+		drv_data->hw_fence_mem_fences_table_size);
+	for (i = 0; i < HW_FENCE_MAX_CLIENT_TYPE; i++) {
+		desc = &hw_fence_client_types[i];
 		for (j = 0; j < desc->clients_num; j++) {
-			drv_data->hw_fence_client_queue_size[desc->init_id + j] =
+			enum hw_fence_client_id client_id_ext = desc->init_id + j;
+			enum hw_fence_client_id client_id =
+				hw_fence_utils_get_client_id_priv(drv_data, client_id_ext);
+
+			drv_data->hw_fence_client_queue_size[client_id] =
 				(struct hw_fence_client_queue_size_desc)
 				{desc->queues_num, desc->queue_entries, desc->mem_size,
 				start_offset};
+			HWFNC_DBG_INIT("%s client_id_ext:%lu client_id:%lu start_offset:%lu\n",
+				desc->name, client_id_ext, client_id, start_offset);
 			start_offset += desc->mem_size;
 		}
 	}
@@ -670,6 +750,7 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
 int hw_fence_utils_parse_dt_props(struct hw_fence_driver_data *drv_data)
 {
 	int ret;
+	size_t size;
 	u32 val = 0;
 
 	ret = of_property_read_u32(drv_data->dev->of_node, "qcom,hw-fence-table-entries", &val);
@@ -721,11 +802,20 @@ int hw_fence_utils_parse_dt_props(struct hw_fence_driver_data *drv_data)
 		return -EINVAL;
 	}
 
+	/* allocate clients */
+
+	size = drv_data->clients_num * sizeof(struct msm_hw_fence_client *);
+	drv_data->clients = kzalloc(size, GFP_KERNEL);
+	if (!drv_data->clients)
+		return -ENOMEM;
+
 	HWFNC_DBG_INIT("table: entries=%lu mem_size=%lu queue: entries=%lu\b",
 		drv_data->hw_fence_table_entries, drv_data->hw_fence_mem_fences_table_size,
 		drv_data->hw_fence_queue_entries);
 	HWFNC_DBG_INIT("ctrl queue: size=%lu mem_size=%lu\b",
 		drv_data->hw_fence_ctrl_queue_size, drv_data->hw_fence_mem_ctrl_queues_size);
+	HWFNC_DBG_INIT("clients_num: %lu, total_mem_size:%lu\n", drv_data->clients_num,
+		drv_data->used_mem_size);
 
 	return 0;
 }
@@ -837,3 +927,31 @@ int hw_fence_utils_map_ctl_start(struct hw_fence_driver_data *drv_data)
 
 	return 0;
 }
+
+enum hw_fence_client_id hw_fence_utils_get_client_id_priv(struct hw_fence_driver_data *drv_data,
+	enum hw_fence_client_id client_id)
+{
+	int i, client_type, offset;
+	enum hw_fence_client_id client_id_priv;
+
+	if (client_id < HW_FENCE_MAX_STATIC_CLIENTS_INDEX)
+		return client_id;
+
+	/* consolidate external 'hw_fence_client_id' enum into consecutive internal client IDs */
+	client_type = HW_FENCE_MAX_CLIENT_TYPE_STATIC +
+		(client_id - HW_FENCE_MAX_STATIC_CLIENTS_INDEX) /
+		MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT;
+	offset = (client_id - HW_FENCE_MAX_STATIC_CLIENTS_INDEX) %
+		MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT;
+
+	/* invalid client id out of range of supported configurable sub-clients */
+	if (offset >= drv_data->hw_fence_client_types[client_type].clients_num)
+		return HW_FENCE_CLIENT_MAX;
+
+	client_id_priv = HW_FENCE_MAX_STATIC_CLIENTS_INDEX + offset;
+
+	for (i = HW_FENCE_MAX_CLIENT_TYPE_STATIC; i < client_type; i++)
+		client_id_priv += drv_data->hw_fence_client_types[i].clients_num;
+
+	return client_id_priv;
+}

+ 4 - 4
hw_fence/src/hw_fence_ioctl.c

@@ -132,9 +132,9 @@ static bool _is_valid_client(struct hw_sync_obj *obj)
 	if (!obj)
 		return false;
 
-	if (obj->client_id < HW_FENCE_CLIENT_ID_VAL0 || obj->client_id >= HW_FENCE_CLIENT_MAX) {
+	if (obj->client_id < HW_FENCE_CLIENT_ID_VAL0 || obj->client_id > HW_FENCE_CLIENT_ID_VAL6) {
 		HWFNC_ERR("invalid client_id:%d min:%d max:%d\n", obj->client_id,
-				HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_MAX);
+				HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_ID_VAL6);
 		return false;
 	}
 
@@ -151,9 +151,9 @@ static int _get_client_id(struct hw_sync_obj *obj, unsigned long arg)
 	if (!obj)
 		return -EINVAL;
 
-	if (client_id < HW_FENCE_CLIENT_ID_VAL0 || client_id >= HW_FENCE_CLIENT_MAX) {
+	if (client_id < HW_FENCE_CLIENT_ID_VAL0 || client_id > HW_FENCE_CLIENT_ID_VAL6) {
 		HWFNC_ERR("invalid client_id:%d min:%d max:%d\n", client_id,
-				HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_MAX);
+				HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_ID_VAL6);
 		return -EINVAL;
 	}
 

+ 34 - 9
hw_fence/src/msm_hw_fence.c

@@ -17,24 +17,33 @@
 struct hw_fence_driver_data *hw_fence_drv_data;
 static bool hw_fence_driver_enable;
 
-void *msm_hw_fence_register(enum hw_fence_client_id client_id,
+void *msm_hw_fence_register(enum hw_fence_client_id client_id_ext,
 	struct msm_hw_fence_mem_addr *mem_descriptor)
 {
 	struct msm_hw_fence_client *hw_fence_client;
+	enum hw_fence_client_id client_id;
 	int ret;
 
-	HWFNC_DBG_H("++ client_id:%d\n", client_id);
+	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) {
 		HWFNC_ERR("hw fence driver not ready\n");
 		return ERR_PTR(-EAGAIN);
 	}
 
-	if (!mem_descriptor || client_id >= HW_FENCE_CLIENT_MAX) {
-		HWFNC_ERR("Invalid params: %d client_id:%d\n",
-			!mem_descriptor, client_id);
+	if (!mem_descriptor || client_id_ext >= HW_FENCE_CLIENT_MAX) {
+		HWFNC_ERR("Invalid params: %d client_id_ext:%d\n",
+			!mem_descriptor, client_id_ext);
 		return ERR_PTR(-EINVAL);
 	}
+
+	client_id = hw_fence_utils_get_client_id_priv(hw_fence_drv_data, client_id_ext);
+	if (client_id >= HW_FENCE_CLIENT_MAX) {
+		HWFNC_ERR("Invalid params: client_id:%d client_id_ext:%d\n",
+			client_id, client_id_ext);
+		return ERR_PTR(-EINVAL);
+	}
+
 	/* Alloc client handle */
 	hw_fence_client =  kzalloc(sizeof(*hw_fence_client), GFP_KERNEL);
 	if (!hw_fence_client)
@@ -54,6 +63,7 @@ void *msm_hw_fence_register(enum hw_fence_client_id client_id,
 	mutex_unlock(&hw_fence_drv_data->clients_register_lock);
 
 	hw_fence_client->client_id = client_id;
+	hw_fence_client->client_id_ext = client_id_ext;
 	hw_fence_client->ipc_client_vid =
 		hw_fence_ipcc_get_client_virt_id(hw_fence_drv_data, client_id);
 	hw_fence_client->ipc_client_pid =
@@ -132,7 +142,7 @@ int msm_hw_fence_deregister(void *client_handle)
 	}
 	hw_fence_client = (struct msm_hw_fence_client *)client_handle;
 
-	if (hw_fence_client->client_id >= HW_FENCE_CLIENT_MAX) {
+	if (hw_fence_client->client_id >= hw_fence_drv_data->clients_num) {
 		HWFNC_ERR("Invalid client_id:%d\n", hw_fence_client->client_id);
 		return -EINVAL;
 	}
@@ -257,7 +267,7 @@ int msm_hw_fence_destroy_with_handle(void *client_handle, u64 handle)
 	}
 	hw_fence_client = (struct msm_hw_fence_client *)client_handle;
 
-	if (hw_fence_client->client_id >= HW_FENCE_CLIENT_MAX) {
+	if (hw_fence_client->client_id >= hw_fence_drv_data->clients_num) {
 		HWFNC_ERR("Invalid client_id:%d\n", hw_fence_client->client_id);
 		return -EINVAL;
 	}
@@ -305,6 +315,12 @@ int msm_hw_fence_wait_update_v2(void *client_handle,
 		return -EINVAL;
 	}
 
+	if (hw_fence_client->client_id > hw_fence_drv_data->rxq_clients_num) {
+		HWFNC_ERR("Transmit-only client client_id:%d client_id_ext:%d register for wait\n",
+			hw_fence_client->client_id, hw_fence_client->client_id_ext);
+		return -EINVAL;
+	}
+
 	HWFNC_DBG_H("+\n");
 
 	/* Process all the list of fences */
@@ -380,10 +396,19 @@ 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)
+int msm_hw_fence_reset_client_by_id(enum hw_fence_client_id client_id_ext, u32 reset_flags)
 {
+	enum hw_fence_client_id client_id;
+
+	if (client_id_ext >= HW_FENCE_CLIENT_MAX) {
+		HWFNC_ERR("Invalid client_id_ext:%d\n", client_id_ext);
+		return -EINVAL;
+	}
+
+	client_id = hw_fence_utils_get_client_id_priv(hw_fence_drv_data, client_id_ext);
+
 	if (client_id >= HW_FENCE_CLIENT_MAX) {
-		HWFNC_ERR("Invalid client_id:%d\n", client_id);
+		HWFNC_ERR("Invalid client_id:%d client_id_ext:%d\n", client_id, client_id_ext);
 		return -EINVAL;
 	}