aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dmatest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/dmatest.c')
-rw-r--r--drivers/dma/dmatest.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index eb1d8641cf5c..2b8661b54eaf 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -214,9 +214,18 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
214 return error_count; 214 return error_count;
215} 215}
216 216
217static void dmatest_callback(void *completion) 217/* poor man's completion - we want to use wait_event_freezable() on it */
218struct dmatest_done {
219 bool done;
220 wait_queue_head_t *wait;
221};
222
223static void dmatest_callback(void *arg)
218{ 224{
219 complete(completion); 225 struct dmatest_done *done = arg;
226
227 done->done = true;
228 wake_up_all(done->wait);
220} 229}
221 230
222/* 231/*
@@ -235,7 +244,9 @@ static void dmatest_callback(void *completion)
235 */ 244 */
236static int dmatest_func(void *data) 245static int dmatest_func(void *data)
237{ 246{
247 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait);
238 struct dmatest_thread *thread = data; 248 struct dmatest_thread *thread = data;
249 struct dmatest_done done = { .wait = &done_wait };
239 struct dma_chan *chan; 250 struct dma_chan *chan;
240 const char *thread_name; 251 const char *thread_name;
241 unsigned int src_off, dst_off, len; 252 unsigned int src_off, dst_off, len;
@@ -252,7 +263,7 @@ static int dmatest_func(void *data)
252 int i; 263 int i;
253 264
254 thread_name = current->comm; 265 thread_name = current->comm;
255 set_freezable_with_signal(); 266 set_freezable();
256 267
257 ret = -ENOMEM; 268 ret = -ENOMEM;
258 269
@@ -306,9 +317,6 @@ static int dmatest_func(void *data)
306 struct dma_async_tx_descriptor *tx = NULL; 317 struct dma_async_tx_descriptor *tx = NULL;
307 dma_addr_t dma_srcs[src_cnt]; 318 dma_addr_t dma_srcs[src_cnt];
308 dma_addr_t dma_dsts[dst_cnt]; 319 dma_addr_t dma_dsts[dst_cnt];
309 struct completion cmp;
310 unsigned long start, tmo, end = 0 /* compiler... */;
311 bool reload = true;
312 u8 align = 0; 320 u8 align = 0;
313 321
314 total_tests++; 322 total_tests++;
@@ -391,9 +399,9 @@ static int dmatest_func(void *data)
391 continue; 399 continue;
392 } 400 }
393 401
394 init_completion(&cmp); 402 done.done = false;
395 tx->callback = dmatest_callback; 403 tx->callback = dmatest_callback;
396 tx->callback_param = &cmp; 404 tx->callback_param = &done;
397 cookie = tx->tx_submit(tx); 405 cookie = tx->tx_submit(tx);
398 406
399 if (dma_submit_error(cookie)) { 407 if (dma_submit_error(cookie)) {
@@ -407,20 +415,20 @@ static int dmatest_func(void *data)
407 } 415 }
408 dma_async_issue_pending(chan); 416 dma_async_issue_pending(chan);
409 417
410 do { 418 wait_event_freezable_timeout(done_wait, done.done,
411 start = jiffies; 419 msecs_to_jiffies(timeout));
412 if (reload)
413 end = start + msecs_to_jiffies(timeout);
414 else if (end <= start)
415 end = start + 1;
416 tmo = wait_for_completion_interruptible_timeout(&cmp,
417 end - start);
418 reload = try_to_freeze();
419 } while (tmo == -ERESTARTSYS);
420 420
421 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 421 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
422 422
423 if (tmo == 0) { 423 if (!done.done) {
424 /*
425 * We're leaving the timed out dma operation with
426 * dangling pointer to done_wait. To make this
427 * correct, we'll need to allocate wait_done for
428 * each test iteration and perform "who's gonna
429 * free it this time?" dancing. For now, just
430 * leave it dangling.
431 */
424 pr_warning("%s: #%u: test timed out\n", 432 pr_warning("%s: #%u: test timed out\n",
425 thread_name, total_tests - 1); 433 thread_name, total_tests - 1);
426 failed_tests++; 434 failed_tests++;