Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79d06d4d authored by Marko Ristola's avatar Marko Ristola Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarMarko M. Ristola <marko.ristola@kolumbus.fi>
Reviewed-by: default avatarManu Abraham <manu@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent fa0d1187
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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) {
+1 −1
Original line number Diff line number Diff line
@@ -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) {
+1 −4
Original line number Diff line number Diff line
@@ -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;
+35 −57
Original line number Diff line number Diff line
@@ -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 @@ 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;
@@ -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();
	RISC_FLUSH(risc_pos);

	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
		mantis->line_count, mantis->line_bytes);
	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->line_count; line++) {
		dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
		if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
			RISC_INSTR(RISC_WRITE	|
	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(((buf_pos / MANTIS_BLOCK_BYTES) +
				   (MANTIS_BLOCK_COUNT - 1)) %
				    MANTIS_BLOCK_COUNT) |
				    mantis->line_bytes);
					   RISC_STATUS(line) |
					   MANTIS_DMA_TR_BYTES);
			} else {
			RISC_INSTR(RISC_WRITE	| mantis->line_bytes);
				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(mantis->buf_dma + buf_pos);
		buf_pos += mantis->line_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);