Commit a276991357c63bfb8d3ffdf5800054dba4f8d558

Authored by Ilya Yanok
Committed by Grant Likely
1 parent ba2eea251f

powerpc/512x: try to free dma descriptors in case of allocation failure

Currently completed descriptors are processed in the tasklet. This can
lead to dead lock in case of CONFIG_NET_DMA enabled (new requests are
submitted from softirq context and dma_memcpy_to_iovec() busy loops until
the requests is submitted). To prevent this we should process completed
descriptors from the allocation failure path in prepare_memcpy too.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
Cc: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

Showing 1 changed file with 45 additions and 34 deletions Side-by-side Diff

drivers/dma/mpc512x_dma.c
... ... @@ -328,19 +328,55 @@
328 328 return IRQ_HANDLED;
329 329 }
330 330  
331   -/* DMA Tasklet */
332   -static void mpc_dma_tasklet(unsigned long data)
  331 +/* proccess completed descriptors */
  332 +static void mpc_dma_process_completed(struct mpc_dma *mdma)
333 333 {
334   - struct mpc_dma *mdma = (void *)data;
335 334 dma_cookie_t last_cookie = 0;
336 335 struct mpc_dma_chan *mchan;
337 336 struct mpc_dma_desc *mdesc;
338 337 struct dma_async_tx_descriptor *desc;
339 338 unsigned long flags;
340 339 LIST_HEAD(list);
341   - uint es;
342 340 int i;
343 341  
  342 + for (i = 0; i < mdma->dma.chancnt; i++) {
  343 + mchan = &mdma->channels[i];
  344 +
  345 + /* Get all completed descriptors */
  346 + spin_lock_irqsave(&mchan->lock, flags);
  347 + if (!list_empty(&mchan->completed))
  348 + list_splice_tail_init(&mchan->completed, &list);
  349 + spin_unlock_irqrestore(&mchan->lock, flags);
  350 +
  351 + if (list_empty(&list))
  352 + continue;
  353 +
  354 + /* Execute callbacks and run dependencies */
  355 + list_for_each_entry(mdesc, &list, node) {
  356 + desc = &mdesc->desc;
  357 +
  358 + if (desc->callback)
  359 + desc->callback(desc->callback_param);
  360 +
  361 + last_cookie = desc->cookie;
  362 + dma_run_dependencies(desc);
  363 + }
  364 +
  365 + /* Free descriptors */
  366 + spin_lock_irqsave(&mchan->lock, flags);
  367 + list_splice_tail_init(&list, &mchan->free);
  368 + mchan->completed_cookie = last_cookie;
  369 + spin_unlock_irqrestore(&mchan->lock, flags);
  370 + }
  371 +}
  372 +
  373 +/* DMA Tasklet */
  374 +static void mpc_dma_tasklet(unsigned long data)
  375 +{
  376 + struct mpc_dma *mdma = (void *)data;
  377 + unsigned long flags;
  378 + uint es;
  379 +
344 380 spin_lock_irqsave(&mdma->error_status_lock, flags);
345 381 es = mdma->error_status;
346 382 mdma->error_status = 0;
... ... @@ -379,35 +415,7 @@
379 415 dev_err(mdma->dma.dev, "- Destination Bus Error\n");
380 416 }
381 417  
382   - for (i = 0; i < mdma->dma.chancnt; i++) {
383   - mchan = &mdma->channels[i];
384   -
385   - /* Get all completed descriptors */
386   - spin_lock_irqsave(&mchan->lock, flags);
387   - if (!list_empty(&mchan->completed))
388   - list_splice_tail_init(&mchan->completed, &list);
389   - spin_unlock_irqrestore(&mchan->lock, flags);
390   -
391   - if (list_empty(&list))
392   - continue;
393   -
394   - /* Execute callbacks and run dependencies */
395   - list_for_each_entry(mdesc, &list, node) {
396   - desc = &mdesc->desc;
397   -
398   - if (desc->callback)
399   - desc->callback(desc->callback_param);
400   -
401   - last_cookie = desc->cookie;
402   - dma_run_dependencies(desc);
403   - }
404   -
405   - /* Free descriptors */
406   - spin_lock_irqsave(&mchan->lock, flags);
407   - list_splice_tail_init(&list, &mchan->free);
408   - mchan->completed_cookie = last_cookie;
409   - spin_unlock_irqrestore(&mchan->lock, flags);
410   - }
  418 + mpc_dma_process_completed(mdma);
411 419 }
412 420  
413 421 /* Submit descriptor to hardware */
414 422  
... ... @@ -587,8 +595,11 @@
587 595 }
588 596 spin_unlock_irqrestore(&mchan->lock, iflags);
589 597  
590   - if (!mdesc)
  598 + if (!mdesc) {
  599 + /* try to free completed descriptors */
  600 + mpc_dma_process_completed(mdma);
591 601 return NULL;
  602 + }
592 603  
593 604 mdesc->error = 0;
594 605 tcd = mdesc->tcd;