aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-03-25 12:13:25 -0400
committerDan Williams <dan.j.williams@intel.com>2009-03-25 12:13:25 -0400
commite44e0aa3cfa97cddff01704751a4b25151830c72 (patch)
tree9d876e5e47813101a4fc125831e0188664c486e0 /drivers/dma
parentb54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0c (diff)
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 <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dmatest.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 224acf478fec..a27c0fb1bc11 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,
196 return error_count; 196 return error_count;
197} 197}
198 198
199static void dmatest_callback(void *completion)
200{
201 complete(completion);
202}
203
199/* 204/*
200 * This function repeatedly tests DMA transfers of various lengths and 205 * This function repeatedly tests DMA transfers of various lengths and
201 * offsets for a given operation type until it is told to exit by 206 * offsets for a given operation type until it is told to exit by
@@ -261,13 +266,17 @@ static int dmatest_func(void *data)
261 } 266 }
262 thread->dsts[i] = NULL; 267 thread->dsts[i] = NULL;
263 268
264 flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP; 269 set_user_nice(current, 10);
270
271 flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
265 272
266 while (!kthread_should_stop()) { 273 while (!kthread_should_stop()) {
267 struct dma_device *dev = chan->device; 274 struct dma_device *dev = chan->device;
268 struct dma_async_tx_descriptor *tx = NULL; 275 struct dma_async_tx_descriptor *tx = NULL;
269 dma_addr_t dma_srcs[src_cnt]; 276 dma_addr_t dma_srcs[src_cnt];
270 dma_addr_t dma_dsts[dst_cnt]; 277 dma_addr_t dma_dsts[dst_cnt];
278 struct completion cmp;
279 unsigned long tmo = msecs_to_jiffies(3000);
271 280
272 total_tests++; 281 total_tests++;
273 282
@@ -318,7 +327,10 @@ static int dmatest_func(void *data)
318 failed_tests++; 327 failed_tests++;
319 continue; 328 continue;
320 } 329 }
321 tx->callback = NULL; 330
331 init_completion(&cmp);
332 tx->callback = dmatest_callback;
333 tx->callback_param = &cmp;
322 cookie = tx->tx_submit(tx); 334 cookie = tx->tx_submit(tx);
323 335
324 if (dma_submit_error(cookie)) { 336 if (dma_submit_error(cookie)) {
@@ -332,18 +344,23 @@ static int dmatest_func(void *data)
332 } 344 }
333 dma_async_issue_pending(chan); 345 dma_async_issue_pending(chan);
334 346
335 do { 347 tmo = wait_for_completion_timeout(&cmp, tmo);
336 msleep(1); 348 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
337 status = dma_async_is_tx_complete(
338 chan, cookie, NULL, NULL);
339 } while (status == DMA_IN_PROGRESS);
340 349
341 if (status == DMA_ERROR) { 350 if (tmo == 0) {
342 pr_warning("%s: #%u: error during copy\n", 351 pr_warning("%s: #%u: test timed out\n",
343 thread_name, total_tests - 1); 352 thread_name, total_tests - 1);
353 failed_tests++;
354 continue;
355 } else if (status != DMA_SUCCESS) {
356 pr_warning("%s: #%u: got completion callback,"
357 " but status is \'%s\'\n",
358 thread_name, total_tests - 1,
359 status == DMA_ERROR ? "error" : "in progress");
344 failed_tests++; 360 failed_tests++;
345 continue; 361 continue;
346 } 362 }
363
347 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 364 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
348 for (i = 0; i < dst_cnt; i++) 365 for (i = 0; i < dst_cnt; i++)
349 dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, 366 dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size,