[media] Refactor Mantis DMA transfer to deliver 16Kb TS data per interrupt
authorMarko Ristola <marko.ristola@kolumbus.fi>
Sat, 7 Aug 2010 11:16:15 +0000 (08:16 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 25 Sep 2011 11:43:06 +0000 (08:43 -0300)
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 <marko.ristola@kolumbus.fi>
Reviewed-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/mantis/hopper_cards.c
drivers/media/dvb/mantis/mantis_cards.c
drivers/media/dvb/mantis/mantis_common.h
drivers/media/dvb/mantis/mantis_dma.c

index 8bbeebc4ffb1c834697481ddbfecca09143802b4..71622f65c037e0e7c297fefe5ac0b8e50b95e49b 100644 (file)
@@ -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) {
index e6c8368782e02b3ba9aa105d76301bd3dfb8d81c..c2bb90b3e52998f424a8dcb13fb4d3098bc6efdc 100644 (file)
@@ -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) {
index 49dbca145bb8e3ae13aa47eb77fdfecf74c0462d..f2410cf0a6bf0ec980b475f8785d5afb7a58ec52 100644 (file)
@@ -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;
index 46202a4012aac8331d343769c449d50d73c1280e..c61ca7d3daea41c217ad2f29821bb468e509a452 100644 (file)
 #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);