On 29/05/2019 11.37, Peter Ujfalusi wrote: > With the polled parameter the DMA drivers can be tested if they can work > correctly when no completion is requested (no DMA_PREP_INTERRUPT and no > callback is provided). > > If polled mode is selected then use dma_sync_wait() to execute the test > iteration instead of relying on the completion callback. > > Signed-off-by: Peter Ujfalusi <peter.ujfalusi@xxxxxx> > --- > drivers/dma/dmatest.c | 35 ++++++++++++++++++++++++++++------- > 1 file changed, 28 insertions(+), 7 deletions(-) > > diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c > index b96814a7dceb..088086d041e9 100644 > --- a/drivers/dma/dmatest.c > +++ b/drivers/dma/dmatest.c > @@ -75,6 +75,10 @@ static bool norandom; > module_param(norandom, bool, 0644); > MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)"); > > +static bool polled; > +module_param(polled, bool, S_IRUGO | S_IWUSR); > +MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts"); > + > static bool verbose; > module_param(verbose, bool, S_IRUGO | S_IWUSR); > MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)"); > @@ -113,6 +117,7 @@ struct dmatest_params { > bool norandom; > int alignment; > unsigned int transfer_size; > + bool polled; > }; > > /** > @@ -654,7 +659,10 @@ static int dmatest_func(void *data) > /* > * src and dst buffers are freed by ourselves below > */ > - flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; > + if (params->polled) > + flags = DMA_CTRL_ACK; > + else > + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; > > ktime = ktime_get(); > while (!kthread_should_stop() > @@ -783,8 +791,10 @@ static int dmatest_func(void *data) > } > > done->done = false; > - tx->callback = dmatest_callback; > - tx->callback_param = done; > + if (!params->polled) { > + tx->callback = dmatest_callback; > + tx->callback_param = done; > + } > cookie = tx->tx_submit(tx); > > if (dma_submit_error(cookie)) { > @@ -793,12 +803,22 @@ static int dmatest_func(void *data) > msleep(100); > goto error_unmap_continue; > } > - dma_async_issue_pending(chan); > > - wait_event_freezable_timeout(thread->done_wait, done->done, > - msecs_to_jiffies(params->timeout)); > + if (params->polled) { > + status = dma_sync_wait(chan, cookie); > + dmaengine_terminate_sync(chan); > + if (status == DMA_COMPLETE) > + done->done = true; I think the main question is how polling for completion should be handled when client does not request for completion interrupt, thus we will have no callback in the DMA driver when the transfer is completed. If DMA_PREP_INTERRUPT is set for the tx_descriptor then the polling will wait until the DMA driver internally receives the interrupt that the transfer is done and sets the cookie to completed state. However if DMA_PREP_INTERRUPT is not set, the DMA driver will not get notification from the HW that is the transfer is done, the only way to know is to check the tx_status and based on the residue (if it is 0 then it is done) decide what to tell the client. Should the client call dmaengine_terminate_* after the polling returned unconditionally to free up the descriptor? Or client should only call dmaengine_terminate_* in case the polling returned with !DMA_COMPLETE and the DMA driver must clean things up before returning if the transfer is completed (residue == 0)? > + } else { > + dma_async_issue_pending(chan); > + > + wait_event_freezable_timeout(thread->done_wait, > + done->done, > + msecs_to_jiffies(params->timeout)); > > - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); > + status = dma_async_is_tx_complete(chan, cookie, NULL, > + NULL); > + } > > if (!done->done) { > result("test timed out", total_tests, src->off, dst->off, > @@ -1068,6 +1088,7 @@ static void add_threaded_test(struct dmatest_info *info) > params->norandom = norandom; > params->alignment = alignment; > params->transfer_size = transfer_size; > + params->polled = polled; > > request_channels(info, DMA_MEMCPY); > request_channels(info, DMA_MEMSET); > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki