return 0;
}
+static int
+hisi_dma_vchan_status(const struct rte_dma_dev *dev, uint16_t vchan,
+ enum rte_dma_vchan_status *status)
+{
+ struct hisi_dma_dev *hw = dev->data->dev_private;
+ uint32_t val;
+
+ RTE_SET_USED(vchan);
+
+ val = hisi_dma_read_queue(hw, HISI_DMA_QUEUE_FSM_REG);
+ val = FIELD_GET(HISI_DMA_QUEUE_FSM_STS_M, val);
+ if (val == HISI_DMA_STATE_RUN)
+ *status = RTE_DMA_VCHAN_ACTIVE;
+ else if (val == HISI_DMA_STATE_CPL)
+ *status = RTE_DMA_VCHAN_IDLE;
+ else
+ *status = RTE_DMA_VCHAN_HALTED_ERROR;
+
+ return 0;
+}
+
static void
hisi_dma_dump_range(struct hisi_dma_dev *hw, FILE *f, uint32_t start,
uint32_t end)
uint16_t count = 0;
uint64_t misc;
- while (true) {
+ while (count < hw->cq_depth) {
cqe = &hw->cqe[cq_head];
misc = cqe->misc;
misc = rte_le_to_cpu_64(misc);
break;
csq_head = FIELD_GET(CQE_SQ_HEAD_MASK, misc);
+ if (unlikely(csq_head > hw->sq_depth_mask)) {
+ /**
+ * Defensive programming to prevent overflow of the
+ * status array indexed by csq_head. Only error logs
+ * are used for prompting.
+ */
+ HISI_DMA_ERR(hw, "invalid csq_head:%u!\n", csq_head);
+ count = 0;
+ break;
+ }
if (unlikely(misc & CQE_STATUS_MASK))
hw->status[csq_head] = FIELD_GET(CQE_STATUS_MASK,
misc);
* dev_stop| |
* | v
* ------------------
+ * | CPL |
+ * ------------------
+ * ^ |
+ * hardware | |
+ * completed all| |dev_submit
+ * descriptors | |
+ * | |
+ * ------------------
* | RUN |
* ------------------
*
.vchan_setup = hisi_dma_vchan_setup,
.stats_get = hisi_dma_stats_get,
.stats_reset = hisi_dma_stats_reset,
+ .vchan_status = hisi_dma_vchan_status,
.dev_dump = hisi_dma_dump,
};