diff options
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h | 15 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c | 48 |
2 files changed, 51 insertions, 12 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h index 71f45d5283..d14d434217 100644 --- a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h +++ b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h @@ -270,7 +270,20 @@ struct grspw_core_stats { * Used to enable RX DMA interrupt * when rx_irq_en_cnt=0. */ -#define DMAFLAG2_MASK (DMAFLAG2_TXIE | DMAFLAG2_RXIE) +/* Defines how the ISR will disable RX/TX DMA interrupt source when a DMA RX/TX + * interrupt has happended. DMA Error Interrupt always disables both RX/TX DMA + * interrupt. By default both RX/TX IRQs are disabled when either a RX, TX or + * both RX/TX DMA interrupt has been requested. The work-task, custom + * application handler or custom ISR handler is responsible to re-enable + * DMA interrupts. + */ +#define DMAFLAG2_IRQD_SRC 0x01000000 /* Disable triggering RX/TX source */ +#define DMAFLAG2_IRQD_NONE 0x00c00000 /* Never disable RX/TX IRQ in ISR */ +#define DMAFLAG2_IRQD_BOTH 0x00000000 /* Always disable both RX/TX sources */ +#define DMAFLAG2_IRQD_MASK 0x01c00000 /* Mask of options */ +#define DMAFLAG2_IRQD_BIT 22 + +#define DMAFLAG2_MASK (DMAFLAG2_TXIE | DMAFLAG2_RXIE | DMAFLAG2_IRQD_MASK) struct grspw_dma_config { int flags; /* DMA config flags, see DMAFLAG1&2_* options */ diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c index b64a807d99..6b5390fffd 100644 --- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c +++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c @@ -2625,10 +2625,21 @@ static void grspw_work_dma_func(struct grspw_dma_priv *dma, unsigned int msg) default: break; } + if (msg == 0) + return; rx_cond_true = 0; tx_cond_true = 0; + if ((dma->cfg.flags & DMAFLAG2_IRQD_MASK) == DMAFLAG2_IRQD_BOTH) { + /* In case both interrupt sources are disabled simultaneously + * by the ISR the re-enabling of the interrupt source must also + * do so to avoid missing interrupts. Both RX and TX process + * will be forced. + */ + msg |= WORK_DMA_RX_MASK | WORK_DMA_TX_MASK; + } + if (msg & WORK_DMA_RX_MASK) { /* Do RX Work */ @@ -2726,7 +2737,7 @@ STATIC void grspw_isr(void *data) unsigned int dma_stat, stat, stat_clrmsk, ctrl, icctrl, timecode, irqs; unsigned int rxirq, rxack, intto; int i, handled = 0, call_user_int_isr; - unsigned int message = WORK_NONE; + unsigned int message = WORK_NONE, dma_en; #ifdef RTEMS_HAS_SMP IRQFLAGS_TYPE irqflags; #endif @@ -2839,26 +2850,41 @@ STATIC void grspw_isr(void *data) if (!irqs) continue; - /* Disable Further IRQs (until enabled again) - * from this DMA channel. Let the status - * bit remain so that they can be handled by - * work function. - */ - REG_WRITE(&priv->regs->dma[i].ctrl, dma_stat & - ~(GRSPW_DMACTRL_RI|GRSPW_DMACTRL_TI| - GRSPW_DMACTRL_PR|GRSPW_DMACTRL_PS| - GRSPW_DMACTRL_RA|GRSPW_DMACTRL_TA| - GRSPW_DMACTRL_AT)); handled = 1; /* DMA error has priority, if error happens it is assumed that * the common work-queue stops the DMA operation for that * channel and makes the DMA tasks exit from their waiting * functions (both RX and TX tasks). + * + * Disable Further IRQs (until enabled again) + * from this DMA channel. Let the status + * bit remain so that they can be handled by + * work function. */ if (irqs & GRSPW_DMA_STATUS_ERROR) { + REG_WRITE(&priv->regs->dma[i].ctrl, dma_stat & + ~(GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI | + GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS | + GRSPW_DMACTRL_RA | GRSPW_DMACTRL_TA | + GRSPW_DMACTRL_AT)); message |= WORK_DMA_ER(i); } else { + /* determine if RX/TX interrupt source(s) shall remain + * enabled. + */ + if (priv->dma[i].cfg.flags & DMAFLAG2_IRQD_SRC) { + dma_en = ~irqs >> 3; + } else { + dma_en = priv->dma[i].cfg.flags >> + (DMAFLAG2_IRQD_BIT - GRSPW_DMACTRL_TI_BIT); + } + dma_en &= (GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI); + REG_WRITE(&priv->regs->dma[i].ctrl, dma_stat & + (~(GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI | + GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS | + GRSPW_DMACTRL_RA | GRSPW_DMACTRL_TA | + GRSPW_DMACTRL_AT) | dma_en)); message |= WORK_DMA(i, irqs >> GRSPW_DMACTRL_PS_BIT); } } |