Skip to content

Commit

Permalink
dma: cppi41: redo descriptor collection in abort case
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sebastian Andrzej Siewior authored and Vinod Koul committed Nov 12, 2013
1 parent 706ff62 commit 1e378a6
Showing 1 changed file with 16 additions and 26 deletions.
42 changes: 16 additions & 26 deletions drivers/dma/cppi41.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,36 +563,26 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
c->td_retry = 100;
}

if (!c->td_seen) {
unsigned td_comp_queue;
if (!c->td_seen || !c->td_desc_seen) {

if (c->is_tx)
td_comp_queue = cdd->td_queue.complete;
else
td_comp_queue = c->q_comp_num;
desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete);
if (!desc_phys)
desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);

desc_phys = cppi41_pop_desc(cdd, td_comp_queue);
if (desc_phys) {
__iormb();
if (desc_phys == c->desc_phys) {
c->td_desc_seen = 1;

} else if (desc_phys == td_desc_phys) {
u32 pd0;

if (desc_phys == td_desc_phys) {
u32 pd0;
pd0 = td->pd0;
WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD);
WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX));
WARN_ON((pd0 & 0x1f) != c->port_num);
} else {
WARN_ON_ONCE(1);
}
c->td_seen = 1;
}
}
if (!c->td_desc_seen) {
desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
if (desc_phys) {
__iormb();
WARN_ON(c->desc_phys != desc_phys);
c->td_desc_seen = 1;
pd0 = td->pd0;
WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD);
WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX));
WARN_ON((pd0 & 0x1f) != c->port_num);
c->td_seen = 1;
} else if (desc_phys) {
WARN_ON_ONCE(1);
}
}
c->td_retry--;
Expand Down

0 comments on commit 1e378a6

Please sign in to comment.