Skip to content

Commit

Permalink
[media] Refactor Mantis DMA transfer to deliver 16Kb TS data per inte…
Browse files Browse the repository at this point in the history
…rrupt

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>
  • Loading branch information
Marko Ristola authored and Mauro Carvalho Chehab committed Sep 25, 2011
1 parent fa0d118 commit 79d06d4
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 63 deletions.
2 changes: 1 addition & 1 deletion drivers/media/dvb/mantis/hopper_cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/dvb/mantis/mantis_cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 1 addition & 4 deletions drivers/media/dvb/mantis/mantis_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
92 changes: 35 additions & 57 deletions drivers/media/dvb/mantis/mantis_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -124,27 +128,6 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis)
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;
Expand All @@ -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:
Expand All @@ -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)
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 79d06d4

Please sign in to comment.