The HW DMA devices supported by IOAT driver do not transition to
the "active" state until the first operation is started by the HW.
Therefore, if the user calls "rte_dma_stop()" on a device without
triggering any operations, the sequence of commands to be sent to
the HW is different, as is the final device state.
Update the IOAT driver "stop" function to take account of this
difference.
Fixes: 583f046dd404 ("dma/ioat: add start and stop")
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Bruce Richardson <[email protected]>
Reviewed-by: Conor Walsh <[email protected]>
Acked-by: Kevin Laatz <[email protected]>
---
drivers/dma/ioat/ioat_dmadev.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/ioat/ioat_dmadev.c b/drivers/dma/ioat/ioat_dmadev.c
index 5906eb45aa..aff7bbbfde 100644
--- a/drivers/dma/ioat/ioat_dmadev.c
+++ b/drivers/dma/ioat/ioat_dmadev.c
@@ -166,17 +166,28 @@ static int
ioat_dev_stop(struct rte_dma_dev *dev)
{
struct ioat_dmadev *ioat = dev->fp_obj->dev_private;
+ unsigned int chansts;
uint32_t retry = 0;
- ioat->regs->chancmd = IOAT_CHANCMD_SUSPEND;
+ chansts = (unsigned int)(ioat->regs->chansts & IOAT_CHANSTS_STATUS);
+ if (chansts == IOAT_CHANSTS_ACTIVE || chansts == IOAT_CHANSTS_IDLE)
+ ioat->regs->chancmd = IOAT_CHANCMD_SUSPEND;
+ else
+ ioat->regs->chancmd = IOAT_CHANCMD_RESET;
do {
rte_pause();
retry++;
- } while ((ioat->regs->chansts & IOAT_CHANSTS_STATUS) !=
IOAT_CHANSTS_SUSPENDED
- && retry < 200);
+ chansts = (unsigned int)(ioat->regs->chansts &
IOAT_CHANSTS_STATUS);
+ } while (chansts != IOAT_CHANSTS_SUSPENDED &&
+ chansts != IOAT_CHANSTS_HALTED && retry < 200);
+
+ if (chansts == IOAT_CHANSTS_SUSPENDED || chansts == IOAT_CHANSTS_HALTED)
+ return 0;
- return ((ioat->regs->chansts & IOAT_CHANSTS_STATUS) ==
IOAT_CHANSTS_SUSPENDED) ? 0 : -1;
+ IOAT_PMD_WARN("Channel could not be suspended on stop. (chansts = %u
[%s])",
+ chansts, chansts_readable[chansts]);
+ return -1;
}
/* Get device information of a device. */
--
2.37.2