Browse Source

video: driver: reset interface queue header for sys error case

interface queues were allocated only once and reused for entire
lifetime, but un-consumed packets in the queue during sys_error
is leading to undefined behaviour for the next session.

For e.x, after queueing cmd_init, received sys_error, so core
will be deinited and sys_init willbe sent again as part of next
session_open, but FW is consuming 1st cmd_init pkt and sending
init_done but driver is expecting done for 2nd cmd_init, So
i.e treated as fatal and driver is closing the session and
doing core_deinit.

To avoid above mentioned issue, made changes to reset queue hdr
incase of sys_error.

Change-Id: I3ebba24ed4975fbf2b16f914c28b9ae72878fb03
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal 2 years ago
parent
commit
3c75f5da07
1 changed files with 46 additions and 21 deletions
  1. 46 21
      driver/vidc/src/venus_hfi.c

+ 46 - 21
driver/vidc/src/venus_hfi.c

@@ -2232,11 +2232,49 @@ void venus_hfi_interface_queues_deinit(struct msm_vidc_core *core)
 	core->sfr.align_device_addr = 0;
 }
 
+static int venus_hfi_reset_queue_header(struct msm_vidc_core *core)
+{
+	struct msm_vidc_iface_q_info *iface_q;
+	struct hfi_queue_header *q_hdr;
+	int i, rc = 0;
+
+	if (!core) {
+		d_vpr_e("%s: invalid param\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
+		iface_q = &core->iface_queues[i];
+		__set_queue_hdr_defaults(iface_q->q_hdr);
+	}
+
+	iface_q = &core->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
+
+	iface_q = &core->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
+
+	iface_q = &core->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
+	/*
+	 * Set receive request to zero on debug queue as there is no
+	 * need of interrupt from video hardware for debug messages
+	 */
+	q_hdr->qhdr_rx_req = 0;
+
+	return rc;
+}
+
 int venus_hfi_interface_queues_init(struct msm_vidc_core *core)
 {
 	int rc = 0;
 	struct hfi_queue_table_header *q_tbl_hdr;
-	struct hfi_queue_header *q_hdr;
 	struct msm_vidc_iface_q_info *iface_q;
 	struct msm_vidc_alloc alloc;
 	struct msm_vidc_map map;
@@ -2247,6 +2285,7 @@ int venus_hfi_interface_queues_init(struct msm_vidc_core *core)
 
 	if (core->iface_q_table.align_virtual_addr) {
 		d_vpr_h("%s: queues already allocated\n", __func__);
+		venus_hfi_reset_queue_header(core);
 		return 0;
 	}
 
@@ -2287,7 +2326,6 @@ int venus_hfi_interface_queues_init(struct msm_vidc_core *core)
 		offset += iface_q->q_array.mem_size;
 		iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
 				core->iface_q_table.align_virtual_addr, i);
-		__set_queue_hdr_defaults(iface_q->q_hdr);
 	}
 
 	q_tbl_hdr = (struct hfi_queue_table_header *)
@@ -2301,25 +2339,12 @@ int venus_hfi_interface_queues_init(struct msm_vidc_core *core)
 	q_tbl_hdr->qtbl_num_q = VIDC_IFACEQ_NUMQ;
 	q_tbl_hdr->qtbl_num_active_q = VIDC_IFACEQ_NUMQ;
 
-	iface_q = &core->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
-
-	iface_q = &core->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
-
-	iface_q = &core->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
-	/*
-	 * Set receive request to zero on debug queue as there is no
-	 * need of interrupt from video hardware for debug messages
-	 */
-	q_hdr->qhdr_rx_req = 0;
+	/* reset hfi queue header fields */
+	rc = venus_hfi_reset_queue_header(core);
+	if (rc) {
+		d_vpr_e("%s: init queue header failed\n", __func__);
+		goto fail_alloc_queue;
+	}
 
 	/* sfr buffer */
 	memset(&alloc, 0, sizeof(alloc));