Thank you again Andy

On 05/15/2011 10:31 PM, Andy Walls wrote:
On Sun, 2011-05-15 at 14:48 +0200, Ramon Hofer wrote:
Hi list

I have a WinTV PVR 500 and the "ivtv0: DMA TIMEOUT" problem which I'm
trying to solve for several months now.
After reading through wikis, forum and mailing posts but I'm still not
sure where the problem could be.
Here's the fix:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=d213ad08362909ab50fbd6568fcc9fd568268d29

I'm not sure what kernel version it went into, but it is certainly not
in kernel v2.6.32.

I don't want to do anything wrong so I'd like to ask if this is correct to patch kernel version 2.6.32-5-amd64: I found this Debian kernel handbook: http://kernel-handbook.alioth.debian.org/ch-common-tasks.html

# apt-get install linux-source-2.6.32
$ cd ~/System
$ tar jxf /usr/src/linux-source-2.6.32.tar.bz2

But when I try to apply the patch I get the following:
$ patch -p1 < ivtv.patch
patching file drivers/media/video/ivtv/ivtv-irq.c
Hunk #1 FAILED at 628.
1 out of 1 hunk FAILED -- saving rejects to file drivers/media/video/ivtv/ivtv-irq.c.rej


I created ivtv.patch which contains:

$ cat ivtv.patch
diff --git a/drivers/media/video/ivtv/ivtv-irq.c <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9b4faf009196afad6de8f4b3ffeebc0dbd2f05e6> b/drivers/media/video/ivtv/ivtv-irq.c <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9c29e964d400b955d36074487c17c22e1195bbcd;hb=d213ad08362909ab50fbd6568fcc9fd568268d29> index 9b4faf0 <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9b4faf009196afad6de8f4b3ffeebc0dbd2f05e6>..9c29e96 <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9c29e964d400b955d36074487c17c22e1195bbcd;hb=d213ad08362909ab50fbd6568fcc9fd568268d29> 100644(file) --- a/drivers/media/video/ivtv/ivtv-irq.c <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9b4faf009196afad6de8f4b3ffeebc0dbd2f05e6> +++ b/drivers/media/video/ivtv/ivtv-irq.c <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9c29e964d400b955d36074487c17c22e1195bbcd;hb=d213ad08362909ab50fbd6568fcc9fd568268d29> @@ -628,22 <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9b4faf009196afad6de8f4b3ffeebc0dbd2f05e6#l628> +628,66 <http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/media/video/ivtv/ivtv-irq.c;h=9c29e964d400b955d36074487c17c22e1195bbcd;hb=d213ad08362909ab50fbd6568fcc9fd568268d29#l628> @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
 static void ivtv_irq_dma_err(struct ivtv *itv)
 {
        u32 data[CX2341X_MBOX_MAX_DATA];
+       u32 status;
        del_timer(&itv->dma_timer);
+
        ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+       status = read_reg(IVTV_REG_DMASTATUS);
        IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
-                               read_reg(IVTV_REG_DMASTATUS), 
itv->cur_dma_stream);
-       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+                               status, itv->cur_dma_stream);
+       /*
+        * We do *not* write back to the IVTV_REG_DMASTATUS register to
+        * clear the error status, if either the encoder write (0x02) or
+        * decoder read (0x01) bus master DMA operation do not indicate
+        * completed.  We can race with the DMA engine, which may have
+        * transitioned to completed status *after* we read the register.
+        * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the
+        * DMA engine has completed, will cause the DMA engine to stop working.
+        */
+       status &= 0x3;
+       if (status == 0x3)
+               write_reg(status, IVTV_REG_DMASTATUS);
+
        if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
                struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];
-               /* retry */
-               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
+               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+                       /* retry */
+                       /*
+                        * FIXME - handle cases of DMA error similar to
+                        * encoder below, except conditioned on status & 0x1
+                        */
                        ivtv_dma_dec_start(s);
-               else
-                       ivtv_dma_enc_start(s);
-               return;
+                       return;
+               } else {
+                       if ((status & 0x2) == 0) {
+                               /*
+                                * CX2341x Bus Master DMA write is ongoing.
+                                * Reset the timer and let it complete.
+                                */
+                               itv->dma_timer.expires =
+                                               jiffies + msecs_to_jiffies(600);
+                               add_timer(&itv->dma_timer);
+                               return;
+                       }
+
+                       if (itv->dma_retries < 3) {
+                               /*
+                                * CX2341x Bus Master DMA write has ended.
+                                * Retry the write, starting with the first
+                                * xfer segment. Just retrying the current
+                                * segment is not sufficient.
+                                */
+                               s->sg_processed = 0;
+                               itv->dma_retries++;
+                               ivtv_dma_enc_start_xfer(s);
+                               return;
+                       }
+                       /* Too many retries, give up on this one */
+               }
+
        }
        if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
                ivtv_udma_start(itv);


The rejects which were save to the file drivers/media/video/ivtv/ivtv-irq.c.rej are:

$ cat drivers/media/video/ivtv/ivtv-irq.c.rej
--- drivers/media/video/ivtv/ivtv-irq.c
+++ drivers/media/video/ivtv/ivtv-irq.c
@@ -628,22 +628,66 @@
 static void ivtv_irq_dma_err(struct ivtv *itv)
 {
        u32 data[CX2341X_MBOX_MAX_DATA];
+       u32 status;

        del_timer(&itv->dma_timer);
+
        ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+       status = read_reg(IVTV_REG_DMASTATUS);
        IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
- read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
-       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+                               status, itv->cur_dma_stream);
+       /*
+        * We do *not* write back to the IVTV_REG_DMASTATUS register to
+        * clear the error status, if either the encoder write (0x02) or
+        * decoder read (0x01) bus master DMA operation do not indicate
+        * completed.  We can race with the DMA engine, which may have
+        * transitioned to completed status *after* we read the register.
+ * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the + * DMA engine has completed, will cause the DMA engine to stop working.
+        */
+       status &= 0x3;
+       if (status == 0x3)
+               write_reg(status, IVTV_REG_DMASTATUS);
+
        if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
                struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];

-               /* retry */
-               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
+               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+                       /* retry */
+                       /*
+                        * FIXME - handle cases of DMA error similar to
+                        * encoder below, except conditioned on status & 0x1
+                        */
                        ivtv_dma_dec_start(s);
-               else
-                       ivtv_dma_enc_start(s);
-               return;
+                       return;
+               } else {
+                       if ((status & 0x2) == 0) {
+                               /*
+                                * CX2341x Bus Master DMA write is ongoing.
+                                * Reset the timer and let it complete.
+                                */
+                               itv->dma_timer.expires =
+ jiffies + msecs_to_jiffies(600);
+                               add_timer(&itv->dma_timer);
+                               return;
+                       }
+
+                       if (itv->dma_retries < 3) {
+                               /*
+                                * CX2341x Bus Master DMA write has ended.
+                                * Retry the write, starting with the first
+                                * xfer segment. Just retrying the current
+                                * segment is not sufficient.
+                                */
+                               s->sg_processed = 0;
+                               itv->dma_retries++;
+                               ivtv_dma_enc_start_xfer(s);
+                               return;
+                       }
+                       /* Too many retries, give up on this one */
+               }
+
        }
        if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
                ivtv_udma_start(itv);


When I look for the differences between the two files I get:

$ diff ivtv.patch drivers/media/video/ivtv/ivtv-irq.c.rej
1,5c1,3
< diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
< index 9b4faf0..9c29e96 100644 (file)
< --- a/drivers/media/video/ivtv/ivtv-irq.c
< +++ b/drivers/media/video/ivtv/ivtv-irq.c
< @@ -628,22 +628,66 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
---
> --- drivers/media/video/ivtv/ivtv-irq.c
> +++ drivers/media/video/ivtv/ivtv-irq.c
> @@ -628,22 +628,66 @@
79d76
<


Best regards
Ramon


_______________________________________________
ivtv-users mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-users

Reply via email to