From e44e0aa3cfa97cddff01704751a4b25151830c72 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 25 Mar 2009 09:13:25 -0700 Subject: [PATCH] dmatest: add dma interrupts and callbacks Use the callback infrastructure to report driver/hardware hangs or missed interrupts. Since this makes the test threads much more aggressive (from: explicit 1ms sleep to: wait_for_completion) we set the nice value to 10 so as to not swamp legitimate tasks. Signed-off-by: Dan Williams --- drivers/dma/dmatest.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 224acf478fe..a27c0fb1bc1 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -196,6 +196,11 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start, return error_count; } +static void dmatest_callback(void *completion) +{ + complete(completion); +} + /* * This function repeatedly tests DMA transfers of various lengths and * offsets for a given operation type until it is told to exit by @@ -261,13 +266,17 @@ static int dmatest_func(void *data) } thread->dsts[i] = NULL; - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP; + set_user_nice(current, 10); + + flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; while (!kthread_should_stop()) { struct dma_device *dev = chan->device; struct dma_async_tx_descriptor *tx = NULL; dma_addr_t dma_srcs[src_cnt]; dma_addr_t dma_dsts[dst_cnt]; + struct completion cmp; + unsigned long tmo = msecs_to_jiffies(3000); total_tests++; @@ -318,7 +327,10 @@ static int dmatest_func(void *data) failed_tests++; continue; } - tx->callback = NULL; + + init_completion(&cmp); + tx->callback = dmatest_callback; + tx->callback_param = &cmp; cookie = tx->tx_submit(tx); if (dma_submit_error(cookie)) { @@ -332,18 +344,23 @@ static int dmatest_func(void *data) } dma_async_issue_pending(chan); - do { - msleep(1); - status = dma_async_is_tx_complete( - chan, cookie, NULL, NULL); - } while (status == DMA_IN_PROGRESS); + tmo = wait_for_completion_timeout(&cmp, tmo); + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); - if (status == DMA_ERROR) { - pr_warning("%s: #%u: error during copy\n", - thread_name, total_tests - 1); + if (tmo == 0) { + pr_warning("%s: #%u: test timed out\n", + thread_name, total_tests - 1); + failed_tests++; + continue; + } else if (status != DMA_SUCCESS) { + pr_warning("%s: #%u: got completion callback," + " but status is \'%s\'\n", + thread_name, total_tests - 1, + status == DMA_ERROR ? "error" : "in progress"); failed_tests++; continue; } + /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ for (i = 0; i < dst_cnt; i++) dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size,