aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-05-26 08:52:34 -0400
committerVinod Koul <vinod.koul@intel.com>2014-07-01 02:45:48 -0400
commit13bbfb5c4eb4fc85bf977245f9b3624df0187184 (patch)
tree87d101762d6454fcb9091dd7b76c8bbc59f7f625
parent4c834452aad01531db949414f94f817a86348d59 (diff)
dma: cppi41: handle 0-length packets
When a 0-length packet is received on the bus, desc->pd0 yields 1, which confuses the driver's users. This information is clearly wrong and not in accordance to the datasheet, but it's been observed on an AM335x board, very reproducible. Fix this by looking at bit 19 in PD2 of the completed packet. This bit will tell us if a zero-length packet was received on a queue. If it's set, ignore the value in PD0 and report a total length of 0 instead. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/cppi41.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c
index d028f36ae655..8f8b0b608875 100644
--- a/drivers/dma/cppi41.c
+++ b/drivers/dma/cppi41.c
@@ -86,6 +86,9 @@
86 86
87#define USBSS_IRQ_PD_COMP (1 << 2) 87#define USBSS_IRQ_PD_COMP (1 << 2)
88 88
89/* Packet Descriptor */
90#define PD2_ZERO_LENGTH (1 << 19)
91
89struct cppi41_channel { 92struct cppi41_channel {
90 struct dma_chan chan; 93 struct dma_chan chan;
91 struct dma_async_tx_descriptor txd; 94 struct dma_async_tx_descriptor txd;
@@ -307,7 +310,7 @@ static irqreturn_t cppi41_irq(int irq, void *data)
307 __iormb(); 310 __iormb();
308 311
309 while (val) { 312 while (val) {
310 u32 desc; 313 u32 desc, len;
311 314
312 q_num = __fls(val); 315 q_num = __fls(val);
313 val &= ~(1 << q_num); 316 val &= ~(1 << q_num);
@@ -319,9 +322,13 @@ static irqreturn_t cppi41_irq(int irq, void *data)
319 q_num, desc); 322 q_num, desc);
320 continue; 323 continue;
321 } 324 }
322 c->residue = pd_trans_len(c->desc->pd6) -
323 pd_trans_len(c->desc->pd0);
324 325
326 if (c->desc->pd2 & PD2_ZERO_LENGTH)
327 len = 0;
328 else
329 len = pd_trans_len(c->desc->pd0);
330
331 c->residue = pd_trans_len(c->desc->pd6) - len;
325 dma_cookie_complete(&c->txd); 332 dma_cookie_complete(&c->txd);
326 c->txd.callback(c->txd.callback_param); 333 c->txd.callback(c->txd.callback_param);
327 } 334 }