diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2013-10-22 06:14:05 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2013-11-12 03:58:24 -0500 |
commit | 1e378a6d7789bf142319c6207398367336c49082 (patch) | |
tree | 520f3cdd71c21e1a55df6786a2e5747bc36f7bb1 /drivers/dma | |
parent | 706ff628f0669f28e370d2ad30672e5032dc64b2 (diff) |
dma: cppi41: redo descriptor collection in abort case
Most of the logic here is try and error since what actually happens does
not match the trm or I miss read it.
My first assumption was that the queue on which the tear-down descriptor
completes (their own complete queue vs "active descriptor" complete
queue) depends on the transfer direction. This seems not to be true
because I manage to trigger
| WARN_ON(c->desc_phys != desc_phys);
and the other few were fine means the tear-down descriptor was valid but
on different queue.
This patch changes the logic here to look on both queues for the
descriptor.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/cppi41.c | 42 |
1 files changed, 16 insertions, 26 deletions
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 2500f60393f4..ec87492cfb07 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c | |||
@@ -563,36 +563,26 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c) | |||
563 | c->td_retry = 100; | 563 | c->td_retry = 100; |
564 | } | 564 | } |
565 | 565 | ||
566 | if (!c->td_seen) { | 566 | if (!c->td_seen || !c->td_desc_seen) { |
567 | unsigned td_comp_queue; | ||
568 | 567 | ||
569 | if (c->is_tx) | 568 | desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete); |
570 | td_comp_queue = cdd->td_queue.complete; | 569 | if (!desc_phys) |
571 | else | 570 | desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); |
572 | td_comp_queue = c->q_comp_num; | ||
573 | 571 | ||
574 | desc_phys = cppi41_pop_desc(cdd, td_comp_queue); | 572 | if (desc_phys == c->desc_phys) { |
575 | if (desc_phys) { | 573 | c->td_desc_seen = 1; |
576 | __iormb(); | 574 | |
575 | } else if (desc_phys == td_desc_phys) { | ||
576 | u32 pd0; | ||
577 | 577 | ||
578 | if (desc_phys == td_desc_phys) { | ||
579 | u32 pd0; | ||
580 | pd0 = td->pd0; | ||
581 | WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD); | ||
582 | WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX)); | ||
583 | WARN_ON((pd0 & 0x1f) != c->port_num); | ||
584 | } else { | ||
585 | WARN_ON_ONCE(1); | ||
586 | } | ||
587 | c->td_seen = 1; | ||
588 | } | ||
589 | } | ||
590 | if (!c->td_desc_seen) { | ||
591 | desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); | ||
592 | if (desc_phys) { | ||
593 | __iormb(); | 578 | __iormb(); |
594 | WARN_ON(c->desc_phys != desc_phys); | 579 | pd0 = td->pd0; |
595 | c->td_desc_seen = 1; | 580 | WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD); |
581 | WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX)); | ||
582 | WARN_ON((pd0 & 0x1f) != c->port_num); | ||
583 | c->td_seen = 1; | ||
584 | } else if (desc_phys) { | ||
585 | WARN_ON_ONCE(1); | ||
596 | } | 586 | } |
597 | } | 587 | } |
598 | c->td_retry--; | 588 | c->td_retry--; |