Add a module parameter to allow tests to terminate transfers after a random delay. This can be used to try to provoke races in the handling of ongoing transfers in drivers' implementations of ->device_terminate_all(). Signed-off-by: Vincent Whitchurch <vincent.whitchurch@xxxxxxxx> --- drivers/dma/dmatest.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index ffe621695e47..c3a7681efea8 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -88,6 +88,12 @@ static bool polled; module_param(polled, bool, 0644); MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts"); +/* Note that throughput stats can be misleading when this is used. */ +static unsigned int terminate_delay_us; +module_param(terminate_delay_us, uint, 0644); +MODULE_PARM_DESC(terminate_delay_us, + "Terminate transfers after randomly delaying up to the specified time in microseconds (default: no termination)"); + /** * struct dmatest_params - test parameters. * @buf_size: size of the memcpy test buffer @@ -684,6 +690,7 @@ static int dmatest_func(void *data) (params->iterations && total_tests >= params->iterations))) { struct dma_async_tx_descriptor *tx = NULL; struct dmaengine_unmap_data *um; + bool terminated = false; dma_addr_t *dsts; unsigned int len; @@ -827,19 +834,27 @@ static int dmatest_func(void *data) } else { dma_async_issue_pending(chan); - wait_event_freezable_timeout(thread->done_wait, - done->done, - msecs_to_jiffies(params->timeout)); + if (terminate_delay_us) { + fsleep(dmatest_random() % terminate_delay_us); + + dmaengine_terminate_sync(chan); + terminated = true; + } + + if (!terminated) + wait_event_freezable_timeout(thread->done_wait, + done->done, + msecs_to_jiffies(params->timeout)); status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); } - if (!done->done) { + if (!terminated && !done->done) { result("test timed out", total_tests, src->off, dst->off, len, 0); goto error_unmap_continue; - } else if (status != DMA_COMPLETE && + } else if (!terminated && status != DMA_COMPLETE && !(dma_has_cap(DMA_COMPLETION_NO_ORDER, dev->cap_mask) && status == DMA_OUT_OF_ORDER)) { @@ -852,9 +867,11 @@ static int dmatest_func(void *data) dmaengine_unmap_put(um); - if (params->noverify) { - verbose_result("test passed", total_tests, src->off, - dst->off, len, 0); + if (params->noverify || terminated) { + const char *msg = terminated ? "test terminated" : "test passed"; + + verbose_result(msg, total_tests, src->off, dst->off, + len, 0); continue; } --- base-commit: e8d018dd0257f744ca50a729e3d042cf2ec9da65 change-id: 20230322-dmatest-terminate-bad403208afc Best regards, -- Vincent Whitchurch <vincent.whitchurch@xxxxxxxx>