From 79d06d4dff733ee472e1f8933a33317a18195c0c Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Sat, 7 Aug 2010 08:16:15 -0300 Subject: [PATCH] [media] Refactor Mantis DMA transfer to deliver 16Kb TS data per interrupt With VDR streaming HDTV into network, generating an interrupt once per 16kb, implemented in this patch, seems to support more robust throughput with HDTV. Fix leaking almost 64kb data from the previous TS after changing the TS. One effect of the old version was, that the DMA transfer and driver's DMA buffer access might happen at the same time - a race condition. Signed-off-by: Marko M. Ristola Reviewed-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_cards.c | 2 +- drivers/media/dvb/mantis/mantis_cards.c | 2 +- drivers/media/dvb/mantis/mantis_common.h | 5 +- drivers/media/dvb/mantis/mantis_dma.c | 92 +++++++++--------------- 4 files changed, 38 insertions(+), 63 deletions(-) diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 8bbeebc4ffb1..71622f65c037 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -126,7 +126,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) } if (stat & MANTIS_INT_RISCI) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; tasklet_schedule(&mantis->tasklet); } if (stat & MANTIS_INT_I2CDONE) { diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index e6c8368782e0..c2bb90b3e529 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -134,7 +134,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) } if (stat & MANTIS_INT_RISCI) { dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28; tasklet_schedule(&mantis->tasklet); } if (stat & MANTIS_INT_I2CDONE) { diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 49dbca145bb8..f2410cf0a6bf 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -123,11 +123,8 @@ struct mantis_pci { unsigned int num; /* RISC Core */ - u32 finished_block; + u32 busy_block; u32 last_block; - u32 line_bytes; - u32 line_count; - u32 risc_pos; u8 *buf_cpu; dma_addr_t buf_dma; u32 *risc_cpu; diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 46202a4012aa..c61ca7d3daea 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -43,13 +43,17 @@ #define RISC_IRQ (0x01 << 24) #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) -#define RISC_FLUSH() (mantis->risc_pos = 0) -#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode)) +#define RISC_FLUSH(risc_pos) (risc_pos = 0) +#define RISC_INSTR(risc_pos, opcode) (mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode)) #define MANTIS_BUF_SIZE (64 * 1024) -#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) -#define MANTIS_BLOCK_COUNT (1 << 4) -#define MANTIS_RISC_SIZE PAGE_SIZE +#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE / 4) +#define MANTIS_DMA_TR_BYTES (2 * 1024) /* upper limit: 4095 bytes. */ +#define MANTIS_BLOCK_COUNT (MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES) + +#define MANTIS_DMA_TR_UNITS (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES) +/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */ +#define MANTIS_RISC_SIZE PAGE_SIZE /* RISC program must fit here. */ int mantis_dma_exit(struct mantis_pci *mantis) { @@ -124,27 +128,6 @@ err: return -ENOMEM; } -static inline int mantis_calc_lines(struct mantis_pci *mantis) -{ - mantis->line_bytes = MANTIS_BLOCK_BYTES; - mantis->line_count = MANTIS_BLOCK_COUNT; - - while (mantis->line_bytes > 4095) { - mantis->line_bytes >>= 1; - mantis->line_count <<= 1; - } - - dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", - MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); - - if (mantis->line_count > 255) { - dprintk(MANTIS_ERROR, 1, "Buffer size error"); - return -EINVAL; - } - - return 0; -} - int mantis_dma_init(struct mantis_pci *mantis) { int err = 0; @@ -158,12 +141,6 @@ int mantis_dma_init(struct mantis_pci *mantis) goto err; } - err = mantis_calc_lines(mantis); - if (err < 0) { - dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); - - goto err; - } return 0; err: @@ -174,31 +151,32 @@ EXPORT_SYMBOL_GPL(mantis_dma_init); static inline void mantis_risc_program(struct mantis_pci *mantis) { u32 buf_pos = 0; - u32 line; + u32 line, step; + u32 risc_pos; dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); - RISC_FLUSH(); - - dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", - mantis->line_count, mantis->line_bytes); - - for (line = 0; line < mantis->line_count; line++) { - dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); - if (!(buf_pos % MANTIS_BLOCK_BYTES)) { - RISC_INSTR(RISC_WRITE | - RISC_IRQ | - RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + - (MANTIS_BLOCK_COUNT - 1)) % - MANTIS_BLOCK_COUNT) | - mantis->line_bytes); - } else { - RISC_INSTR(RISC_WRITE | mantis->line_bytes); - } - RISC_INSTR(mantis->buf_dma + buf_pos); - buf_pos += mantis->line_bytes; + RISC_FLUSH(risc_pos); + + dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u", + MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES); + + for (line = 0; line < MANTIS_BLOCK_COUNT; line++) { + for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) { + dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step); + if (step == 0) { + RISC_INSTR(risc_pos, RISC_WRITE | + RISC_IRQ | + RISC_STATUS(line) | + MANTIS_DMA_TR_BYTES); + } else { + RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES); + } + RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos); + buf_pos += MANTIS_DMA_TR_BYTES; + } } - RISC_INSTR(RISC_JUMP); - RISC_INSTR(mantis->risc_dma); + RISC_INSTR(risc_pos, RISC_JUMP); + RISC_INSTR(risc_pos, mantis->risc_dma); } void mantis_dma_start(struct mantis_pci *mantis) @@ -210,7 +188,7 @@ void mantis_dma_start(struct mantis_pci *mantis) mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); - mantis->last_block = mantis->finished_block = 0; + mantis->last_block = mantis->busy_block = 0; mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); @@ -245,9 +223,9 @@ void mantis_dma_xfer(unsigned long data) struct mantis_pci *mantis = (struct mantis_pci *) data; struct mantis_hwconfig *config = mantis->hwconfig; - while (mantis->last_block != mantis->finished_block) { + while (mantis->last_block != mantis->busy_block) { dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", - mantis->last_block, mantis->finished_block); + mantis->last_block, mantis->busy_block); (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); -- 2.30.2