[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-dvb
Subject:    Re: [linux-dvb] Cinergy C PCI HD with current v4l-dvb - PATCH for
From:       Marko Ristola <marko.ristola () kolumbus ! fi>
Date:       2010-06-19 13:56:24
Message-ID: 4C1CCC88.5 () kolumbus ! fi
[Download RAW message or body]

Hello all interested in a robust Mantis driver.

I have done some Mantis DMA fixes about two to four years ago
into v4l-dvb/linux/drivers/dvb/media/mantis/mantis_dma.c,
but they were discarded then, but the problems remained.
Those fixes helped at least one individual with Cinergy C PCI HD card 
too by lessening the number
of artifacts and making the card usable. I sent the patches for many 
Finnish people at those years.

For Mauro and other maintainers - the patch in this email is now against 
current Mercurial http://linuxtv.org/hg/v4l-dvb branch.
What do you think about this patch? Could you apply it?
I accept that this code may be added to Linux Kernel, or somewhere else, 
licensed as GPLv2.
This code is fully written by me (Marko Ristola).
Signed-off-by: Marko Ristola <marko.ristola@kolumbus.fi>

The patch does two things (other two things are just thoughts, related 
to robustness):
1. Don't flush 64K garbage at stream start, occurs if mantis_dma_start 
is run more than once.
This fix could be done with altering only about two lines of code by 
fixing the broken DMA RISC program code.
(Bug description: At line[0] RISC IRQ will store line=15 on current 
code, causing copying of lines between 0 and 14, and next time 15 from
previous DVB TS stream (total 64K garbage). After that line=0 contains 
current stream, no garbage.
Bug fix description: RISC program must store at interrupt the active 
line variable's value, instead of ( (line - 1) mod 16)).

On my patch, it seems, that risc_step=0 point could be used for the 
interrupt instead of risc_step=1, thus making the code a bit easier to 
understand.

2. Alter DMA transfer so, that each DMA transfer copies only complete
packets (either 188 or 204 bytes) with each DMA transfer.
The hypothesis is that if a DMA transfer transfers only a part of the 
188/204 sized packet,
that packet gets corrupted (last bytes of 2048 sized block).
My DMA transfers are aligned by 64 bytes in CPU memory (DMA buffer start 
+ multiple of 16x(188 or 204)).

3. tasklet_enable/ tasklet_disable for DMA start/stop is commented out 
on my patch.
I think that tasklet enabling maintenance should be done at these 
points, but I don't know
whether the lack of those might cause spin lock failures. Lack of these 
might
cause problems while switching channels (EPG search switches frequency).

4. There is some problem with rmmod mantis, do lsmod:
Module                  Size  Used by
tda10021                5486  4294967291
modprobe mantis
tda10021                5486  4294967292 mantis
So the reference count from mantis to tda10021 gets corrupted at rmmod.
I have Fedora 13 kernel, 2.6.33.5-124.fc13.x86_64

The second modification is the reason for the big number of changes.
This is also the patch, that isn't easily acceptable, because it is hard
to proof that the packets do get corrupted at DMA transfer cutting 
points, or that the hard lockups/reboots are caused
by the DMA transfer misalignment by 188/204 bytes.
The reasoning for the fix is, that without this alignment change there 
were too many artefacts (VDR DVB
recordings lost sound after a while, thus VDR recording feature was 
unusable).
But with these modifications on recordings the sound was usable. Picture 
artefacts weren't so fatal at real time, even
though on Windows side there were much less picture artefacts.

This my code also generates much less interrupts,
because there is one interrupt per 16*188*5=15040 bytes (five DMA 
transfers per interrupt).
Old v4l-dvb version interrupts once per 4096 bytes (two 2048 byte DMA 
transfers per interrupt).

13.06.2010 13:53, cdurrhau@zedat.fu-berlin.de wrote:
> Hello,
>
> once in a while, a server with three Terratec Cinergy C DVB-C PCI HD cards
> will just become unresponsive and the watchdog of the BMC will timeout,
> causing a reset. While this is a good thing - as opposed to just sitting
> there and having crashed - I am digging at the cause.
>
>    
Please try my patch. It might give some help at least with lessening 
interrupts and removing initial garbage.
Do you see any improvement in picture quality or CPU load?

> Hardware has been tested and partly swapped already. Memtest says the 8GB
> ECC memory of Crucial is fine after 48hrs. Power supply has been swapped,
> CPU works fine and I don't see any reason why the system should be too hot
> (neither by touching nor by checking the sensors). Most of the time, the
> CPU (Xeon L3360) is clocked at 2GHz anyway (its just digging in its nose i
> believe). HDD also has no errors according to SMART and to self test.
> The mainboard is an Asus P5BP-E/4L. The cpu is cooled by the boxed HSF,
> additionally, 3 Papst fans blowing air on the hdds (2x 8cm) and sucking
> air out (12cm on the rear). 1 WD VelociRaptor 146GB and 8x WD 1001FALS
> Caviar Black are being used on a 3Ware 7690SA-8i with 9.5.3 codeset
> drivers and firmware.
>    
I think your hardware is okay.
I have Mantis 2033 PCI card. I have had similar issues, but they were
fixable, thus as a result I have a set of patches applied top of public 
ones.

I freshened my mantis_dma.c changes this time. Maybe some or all is accepted
into Mauro's v4l-dvb branch.

> The crash will always happen similar to this (I cannot reproduce it
> safely, though):
> -zap with vdr (streaming out via network, no local output)
> -while running several recordings on different transport streams at the
> same time
> -preferrably on services that dont have highest signal quality
>
> As I said, this will produce a lockup once in a while but of course not if
> you try to reproduce the problem :-)
>
> This is what I get on the remote console via IPMI:
> 40849.442492] BUG: soft lockup - CPU#2 stuck for 61s! [section
> handler:4617]
> [40849.442501] Stack:
> [40849.442501] Call Trace:
> [40849.442501] Code: 48 c7 c2 ae 06 03 81 48 c7 c1 b1 06 03 81 e9 fe
> fe ff ff 90 90 90 90 90 90 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07
> 38 e0 74 06<f3>  90 8a 07 eb f6 c9 c3 66 0f 1f 44 00 00 55 48 89 e5 0f
> b7 07
> [40850.513743] BUG: soft lockup - CPU#3 stuck for 61s! [tuner on
> device:4495]
> [40850.513751] Stack:
> [40850.513751] Call Trace:
> [40850.513751] Code: c2 ae 06 03 81 48 c7 c1 b1 06 03 81 e9 fe fe ff
> ff 90 90 90 90 90 90 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 38 e0
> 74 06 f3 90<8a>  07 eb f6 c9 c3 66 0f 1f 44 00 00 55 48 89 e5 0f b7 07
> 38 e0
>    
I use currently branch http://linuxtv.org/hg/v4l-dvb, usually patched.
I like to test against some current Mauro's v4l-dvb branch, now when 
Mantis changes are merged there.
I need to switch into Git soon though.

> This will then have the watchdog timer time out and cause the configured
> reset to happen via the BMC.
>
> Since I was digging, I found that although I have the 153B:1178 device
> mentioned in mantis_vp2040.h, the dmesg is reporting "VP-2033 found".
> Then, both the tda10021 and tda10023 are loaded (I understand only
> tda10023 should be loaded).
>    
Traditionally Mantis will load and probe all possible drivers.

For historical reasons, I need still to modprobe mantis by hand,
and then the drivers get probed and loaded. Usually PCI device drivers 
get loaded automatically.

Best regards,
Marko Ristola


["mantis_dma_c_fixes.diff" (text/plain)]

diff -r 9652f85e688a linux/drivers/media/dvb/mantis/mantis_dma.c
--- a/linux/drivers/media/dvb/mantis/mantis_dma.c	Thu May 27 02:02:09 2010 -0300
+++ b/linux/drivers/media/dvb/mantis/mantis_dma.c	Sat Jun 19 13:04:49 2010 +0300
@@ -46,11 +46,15 @@
 #define RISC_FLUSH()		(mantis->risc_pos = 0)
 #define RISC_INSTR(opcode)	(mantis->risc_cpu[mantis->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)
+/* (16 * 188) = 3008. (16 * 204) = 3264. x % 64 == 0, x <= 4095 */
+#define RISC_DMA_TR_UNIT(m)     (((m->hwconfig->ts_size == MANTIS_TS_204)? 204:188) * 16)
+#define DMA_TRANSFERS_PER_BLOCK (5)
+#define MANTIS_BLOCK_BYTES(m)   (RISC_DMA_TR_UNIT(m) * DMA_TRANSFERS_PER_BLOCK)
+#define MANTIS_BLOCK_COUNT	(4)
 #define MANTIS_RISC_SIZE	PAGE_SIZE
 
+#define MANTIS_DMA_BUFSZ(m)     (m->line_bytes * m->line_count)
+
 int mantis_dma_exit(struct mantis_pci *mantis)
 {
 	if (mantis->buf_cpu) {
@@ -58,9 +62,9 @@
 			"DMA=0x%lx cpu=0x%p size=%d",
 			(unsigned long) mantis->buf_dma,
 			 mantis->buf_cpu,
-			 MANTIS_BUF_SIZE);
+			 MANTIS_DMA_BUFSZ(mantis));
 
-		pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,
+		pci_free_consistent(mantis->pdev, MANTIS_DMA_BUFSZ(mantis),
 				    mantis->buf_cpu, mantis->buf_dma);
 
 		mantis->buf_cpu = NULL;
@@ -86,7 +90,7 @@
 {
 	if (!mantis->buf_cpu) {
 		mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,
-						       MANTIS_BUF_SIZE,
+						       MANTIS_DMA_BUFSZ(mantis),
 						       &mantis->buf_dma);
 		if (!mantis->buf_cpu) {
 			dprintk(MANTIS_ERROR, 1,
@@ -97,7 +101,8 @@
 		dprintk(MANTIS_ERROR, 1,
 			"DMA=0x%lx cpu=0x%p size=%d",
 			(unsigned long) mantis->buf_dma,
-			mantis->buf_cpu, MANTIS_BUF_SIZE);
+			mantis->buf_cpu,
+			MANTIS_DMA_BUFSZ(mantis));
 	}
 	if (!mantis->risc_cpu) {
 		mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,
@@ -126,18 +131,13 @@
 
 static inline int mantis_calc_lines(struct mantis_pci *mantis)
 {
-	mantis->line_bytes = MANTIS_BLOCK_BYTES;
+	mantis->line_bytes = MANTIS_BLOCK_BYTES(mantis);
 	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]",
+		RISC_DMA_TR_UNIT(mantis), mantis->line_bytes, mantis->line_count);
 
-	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) {
+	if (DMA_TRANSFERS_PER_BLOCK * mantis->line_count > 255) {
 		dprintk(MANTIS_ERROR, 1, "Buffer size error");
 		return -EINVAL;
 	}
@@ -150,6 +150,14 @@
 	int err = 0;
 
 	dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
+
+	err = mantis_calc_lines(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
+
+		goto err;
+	}
+
 	if (mantis_alloc_buffers(mantis) < 0) {
 		dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
 
@@ -158,12 +166,6 @@
 
 		goto err;
 	}
-	err = mantis_calc_lines(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
-
-		goto err;
-	}
 
 	return 0;
 err:
@@ -175,7 +177,9 @@
 {
 	u32 buf_pos = 0;
 	u32 line;
+	u32 step_bytes;
 
+	step_bytes = RISC_DMA_TR_UNIT(mantis);
 	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
 	RISC_FLUSH();
 
@@ -183,19 +187,18 @@
 		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);
+		int risc_step;
+
+		for (risc_step = 0; risc_step < DMA_TRANSFERS_PER_BLOCK; risc_step++) {
+		  u32 en_irq = (risc_step == 1);
+			dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d] risc_step=[%d] en_irq=[%d]", line, risc_step, en_irq);
+			/* Last risc_step: eject IRQ about block completion. */
+			RISC_INSTR(RISC_WRITE |
+				   (en_irq ? (RISC_IRQ | RISC_STATUS(line)) : 0) |
+				   step_bytes);
+			RISC_INSTR(mantis->buf_dma + buf_pos);
+			buf_pos += step_bytes;
 		}
-		RISC_INSTR(mantis->buf_dma + buf_pos);
-		buf_pos += mantis->line_bytes;
 	}
 	RISC_INSTR(RISC_JUMP);
 	RISC_INSTR(mantis->risc_dma);
@@ -205,23 +208,25 @@
 {
 	dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");
 
+	memset(mantis->buf_cpu, 0, MANTIS_DMA_BUFSZ(mantis));
+	mantis->last_block = mantis->finished_block = 0;
 	mantis_risc_program(mantis);
 	mmwrite(mantis->risc_dma, MANTIS_RISC_START);
 	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
 
 	mmwrite(0, MANTIS_DMA_CTL);
-	mantis->last_block = mantis->finished_block = 0;
 
 	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
 
 	mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
 			       | MANTIS_RISC_EN, MANTIS_DMA_CTL);
-
+	//	tasklet_enable(&mantis->tasklet);
 }
 
 void mantis_dma_stop(struct mantis_pci *mantis)
 {
 	u32 stat = 0, mask = 0;
+	//tasklet_disable(&mantis->tasklet);
 
 	stat = mmread(MANTIS_INT_STAT);
 	mask = mmread(MANTIS_INT_MASK);
@@ -246,11 +251,12 @@
 	struct mantis_hwconfig *config = mantis->hwconfig;
 
 	while (mantis->last_block != mantis->finished_block) {
+
 		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
 			mantis->last_block, mantis->finished_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);
-		mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
+		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * mantis->line_bytes], mantis->line_bytes);
+		mantis->last_block = (mantis->last_block + 1) % mantis->line_count;
 	}
 }


_______________________________________________
linux-dvb users mailing list
For V4L/DVB development, please use instead linux-media@vger.kernel.org
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic