Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+27 -10
+27 -10
drivers/dma/dmatest.c
··· 196 196 return error_count; 197 197 } 198 198 199 + static void dmatest_callback(void *completion) 200 + { 201 + complete(completion); 202 + } 203 + 199 204 /* 200 205 * This function repeatedly tests DMA transfers of various lengths and 201 206 * offsets for a given operation type until it is told to exit by ··· 266 261 } 267 262 thread->dsts[i] = NULL; 268 263 269 - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP; 264 + set_user_nice(current, 10); 265 + 266 + flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; 270 267 271 268 while (!kthread_should_stop()) { 272 269 struct dma_device *dev = chan->device; 273 270 struct dma_async_tx_descriptor *tx = NULL; 274 271 dma_addr_t dma_srcs[src_cnt]; 275 272 dma_addr_t dma_dsts[dst_cnt]; 273 + struct completion cmp; 274 + unsigned long tmo = msecs_to_jiffies(3000); 276 275 277 276 total_tests++; 278 277 ··· 327 318 failed_tests++; 328 319 continue; 329 320 } 330 - tx->callback = NULL; 321 + 322 + init_completion(&cmp); 323 + tx->callback = dmatest_callback; 324 + tx->callback_param = &cmp; 331 325 cookie = tx->tx_submit(tx); 332 326 333 327 if (dma_submit_error(cookie)) { ··· 344 332 } 345 333 dma_async_issue_pending(chan); 346 334 347 - do { 348 - msleep(1); 349 - status = dma_async_is_tx_complete( 350 - chan, cookie, NULL, NULL); 351 - } while (status == DMA_IN_PROGRESS); 335 + tmo = wait_for_completion_timeout(&cmp, tmo); 336 + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 352 337 353 - if (status == DMA_ERROR) { 354 - pr_warning("%s: #%u: error during copy\n", 355 - thread_name, total_tests - 1); 338 + if (tmo == 0) { 339 + pr_warning("%s: #%u: test timed out\n", 340 + thread_name, total_tests - 1); 341 + failed_tests++; 342 + continue; 343 + } else if (status != DMA_SUCCESS) { 344 + pr_warning("%s: #%u: got completion callback," 345 + " but status is \'%s\'\n", 346 + thread_name, total_tests - 1, 347 + status == DMA_ERROR ? "error" : "in progress"); 356 348 failed_tests++; 357 349 continue; 358 350 } 351 + 359 352 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 360 353 for (i = 0; i < dst_cnt; i++) 361 354 dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size,