aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/dma.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-02-09 07:28:26 -0500
committerSekhar Nori <nsekhar@ti.com>2012-05-09 07:37:49 -0400
commitbcd59b0f0c14b0584c1213ee3b53d5f84517c419 (patch)
tree09e03c435774d1885e0828aeb7cf2967ac4c56cb /arch/arm/mach-davinci/dma.c
parent477099f189101a6675d93782164446015a3633bd (diff)
ARM: davinci: optimize the DMA ISR
The ISR does quiete a lot of hw access which could be avoided. First it checks for a pending interrupt by reading alteast one register. Then it checks for the "activated" slots by reading another register. This is more or a less a must. Now, once it found an active slot it does the same two reads again. After that it "knows" that there must be a pending transfer however it cross checks with the other register. There are 32 bit in an interger which are polled instead of considering only the set bits and ignoring those which are zero. This performs atleast 32 reads which could be avoided. In case of a first match it does another read. This patch reorganizes the access by re-using the register which have been read and then uses ffs() to find the matching slot instead looping over it. By doing this we get rid of the last (32 + 2 + hits) reads. It is possible however that by really busy bank0 we never get to handle bank1. If this is a problem, we could try to handle bank1 after we are done with bank0 to check if there are any outstanding transfers. To put some numbers on this, this is from spi transfer via spidev. The first column is the number of total transfers, the time stamp is taken before and after the ioctl(): |10000, min: 542us avg: 591us |20000, min: 542us avg: 592us |30000, min: 542us avg: 592us |40000, min: 542us avg: 585us |50000, min: 542us avg: 593us The same test case with the patch applied |10000, min: 444us avg: 493us |20000, min: 444us avg: 491us |30000, min: 444us avg: 489us |40000, min: 444us avg: 491us |50000, min: 444us avg: 492us that is almost 100us that just went away. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'arch/arm/mach-davinci/dma.c')
-rw-r--r--arch/arm/mach-davinci/dma.c69
1 files changed, 34 insertions, 35 deletions
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index fd33919c95d4..8713694a6f2c 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -353,9 +353,10 @@ static int irq2ctlr(int irq)
353 *****************************************************************************/ 353 *****************************************************************************/
354static irqreturn_t dma_irq_handler(int irq, void *data) 354static irqreturn_t dma_irq_handler(int irq, void *data)
355{ 355{
356 int i;
357 int ctlr; 356 int ctlr;
358 unsigned int cnt = 0; 357 u32 sh_ier;
358 u32 sh_ipr;
359 u32 bank;
359 360
360 ctlr = irq2ctlr(irq); 361 ctlr = irq2ctlr(irq);
361 if (ctlr < 0) 362 if (ctlr < 0)
@@ -363,41 +364,39 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
363 364
364 dev_dbg(data, "dma_irq_handler\n"); 365 dev_dbg(data, "dma_irq_handler\n");
365 366
366 if ((edma_shadow0_read_array(ctlr, SH_IPR, 0) == 0) && 367 sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
367 (edma_shadow0_read_array(ctlr, SH_IPR, 1) == 0)) 368 if (!sh_ipr) {
368 return IRQ_NONE; 369 sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
370 if (!sh_ipr)
371 return IRQ_NONE;
372 sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
373 bank = 1;
374 } else {
375 sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
376 bank = 0;
377 }
369 378
370 while (1) { 379 do {
371 int j; 380 u32 slot;
372 if (edma_shadow0_read_array(ctlr, SH_IPR, 0) & 381 u32 channel;
373 edma_shadow0_read_array(ctlr, SH_IER, 0)) 382
374 j = 0; 383 dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
375 else if (edma_shadow0_read_array(ctlr, SH_IPR, 1) & 384
376 edma_shadow0_read_array(ctlr, SH_IER, 1)) 385 slot = __ffs(sh_ipr);
377 j = 1; 386 sh_ipr &= ~(BIT(slot));
378 else 387
379 break; 388 if (sh_ier & BIT(slot)) {
380 dev_dbg(data, "IPR%d %08x\n", j, 389 channel = (bank << 5) | slot;
381 edma_shadow0_read_array(ctlr, SH_IPR, j)); 390 /* Clear the corresponding IPR bits */
382 for (i = 0; i < 32; i++) { 391 edma_shadow0_write_array(ctlr, SH_ICR, bank,
383 int k = (j << 5) + i; 392 BIT(slot));
384 if ((edma_shadow0_read_array(ctlr, SH_IPR, j) & BIT(i)) 393 if (edma_cc[ctlr]->intr_data[channel].callback)
385 && (edma_shadow0_read_array(ctlr, 394 edma_cc[ctlr]->intr_data[channel].callback(
386 SH_IER, j) & BIT(i))) { 395 channel, DMA_COMPLETE,
387 /* Clear the corresponding IPR bits */ 396 edma_cc[ctlr]->intr_data[channel].data);
388 edma_shadow0_write_array(ctlr, SH_ICR, j,
389 BIT(i));
390 if (edma_cc[ctlr]->intr_data[k].callback)
391 edma_cc[ctlr]->intr_data[k].callback(
392 k, DMA_COMPLETE,
393 edma_cc[ctlr]->intr_data[k].
394 data);
395 }
396 } 397 }
397 cnt++; 398 } while (sh_ipr);
398 if (cnt > 10) 399
399 break;
400 }
401 edma_shadow0_write(ctlr, SH_IEVAL, 1); 400 edma_shadow0_write(ctlr, SH_IEVAL, 1);
402 return IRQ_HANDLED; 401 return IRQ_HANDLED;
403} 402}