瀏覽代碼

Merge "mm-drivers: hw_fence: reset queues during client reset"

qctecmdr 2 年之前
父節點
當前提交
e0d65b7cca
共有 3 個文件被更改,包括 48 次插入1 次删除
  1. 2 0
      hw_fence/include/hw_fence_drv_priv.h
  2. 43 0
      hw_fence/src/hw_fence_drv_priv.c
  3. 3 1
      hw_fence/src/msm_hw_fence.c

+ 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)

+ 3 - 1
hw_fence/src/msm_hw_fence.c

@@ -392,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);