diff mbox

dm1105: not demuxing from interrupt context

Message ID 200902190718.47890.liplianin@tut.by (mailing list archive)
State RFC
Headers show

Commit Message

Igor M. Liplianin Feb. 19, 2009, 5:18 a.m. UTC
I read in mailing list about design error in dm1105.
So I am designer.
DMA buffer in the driver itself organized like ringbuffer
and not difficult to bind it to tasklet or work queue.
I choose work queue, because it is like trend :)
The code tested by me on quite fast computer and it works as usual.
I think, on slow computer difference must be noticeable.
The patch is preliminary.
Anyone can criticize.

 
 /* register with input layer */
@@ -717,7 +732,7 @@
 
        dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
        if (!dm1105dvb)
-               goto out;
+               return -ENOMEM;
 
        dm1105dvb->pdev = pdev;
        dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
@@ -747,13 +762,9 @@
        spin_lock_init(&dm1105dvb->lock);
        pci_set_drvdata(pdev, dm1105dvb);
 
-       ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
+       ret = dm1105dvb_hw_init(dm1105dvb);
        if (ret < 0)
                goto err_pci_iounmap;
-
-       ret = dm1105dvb_hw_init(dm1105dvb);
-       if (ret < 0)
-               goto err_free_irq;
 
        /* i2c */
        i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
@@ -820,8 +831,19 @@
 
        dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
        dm1105_ir_init(dm1105dvb);
-out:
-       return ret;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+       INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer, dm1105dvb);
+#else
+       INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
+#endif
+
+       ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
+                                               DRIVER_NAME, dm1105dvb);
+       if (ret < 0)
+               goto err_free_irq;
+
+       return 0;
 
 err_disconnect_frontend:
        dmx->disconnect_frontend(dmx);
@@ -850,7 +872,7 @@
 err_kfree:
        pci_set_drvdata(pdev, NULL);
        kfree(dm1105dvb);
-       goto out;
+       return ret;
 }
 
 static void __devexit dm1105_remove(struct pci_dev *pdev)

Comments

Mauro Carvalho Chehab Feb. 26, 2009, 2:12 p.m. UTC | #1
On Thu, 19 Feb 2009 07:18:47 +0200
"Igor M. Liplianin" <liplianin@tut.by> wrote:

> I read in mailing list about design error in dm1105.
> So I am designer.
> DMA buffer in the driver itself organized like ringbuffer
> and not difficult to bind it to tasklet or work queue.
> I choose work queue, because it is like trend :)
> The code tested by me on quite fast computer and it works as usual.
> I think, on slow computer difference must be noticeable.
> The patch is preliminary.
> Anyone can criticize.

The patch looks fine for me, but, as you said this i preliminary, I'm marking
it as RFC on patchwork. Please send me the final revision of it, after having a
final version.

Cheers,
Mauro.
> 
> diff -r 359d95e1d541 -r f22da8d6a83c linux/drivers/media/dvb/dm1105/dm1105.c
> --- a/linux/drivers/media/dvb/dm1105/dm1105.c   Wed Feb 18 09:49:37 2009 -0300
> +++ b/linux/drivers/media/dvb/dm1105/dm1105.c   Thu Feb 19 04:38:32 2009 +0200
> @@ -220,10 +220,14 @@
>         /* i2c */
>         struct i2c_adapter i2c_adap;
>  
> +       /* irq */
> +       struct work_struct work;
> +
>         /* dma */
>         dma_addr_t dma_addr;
>         unsigned char *ts_buf;
>         u32 wrp;
> +       u32 nextwrp;
>         u32 buffer_size;
>         unsigned int    PacketErrorCount;
>         unsigned int dmarst;
> @@ -418,6 +422,9 @@
>         u8 data;
>         u16 keycode;
>  
> +       if (ir_debug)
> +               printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
> +
>         data = (ircom >> 8) & 0x7f;
>  
>         input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
> @@ -434,6 +441,50 @@
>  
>  }
>  
> +/* work handler */
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> +static void dm1105_dmx_buffer(void *_dm1105dvb)
> +#else
> +static void dm1105_dmx_buffer(struct work_struct *work)
> +#endif
> +{
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> +       struct dm1105dvb *dm1105dvb = _dm1105dvb;
> +#else
> +       struct dm1105dvb *dm1105dvb =
> +                               container_of(work, struct dm1105dvb, work);
> +#endif
> +       unsigned int nbpackets;
> +       u32 oldwrp = dm1105dvb->wrp;
> +       u32 nextwrp = dm1105dvb->nextwrp;
> +
> +       if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
> +                       (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
> +                       (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
> +               dm1105dvb->PacketErrorCount++;
> +               /* bad packet found */
> +               if ((dm1105dvb->PacketErrorCount >= 2) &&
> +                               (dm1105dvb->dmarst == 0)) {
> +                       outb(1, dm_io_mem(DM1105_RST));
> +                       dm1105dvb->wrp = 0;
> +                       dm1105dvb->PacketErrorCount = 0;
> +                       dm1105dvb->dmarst = 0;
> +                       return;
> +               }
> +       }
> +
> +       if (nextwrp < oldwrp) {
> +               memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
> +                                               dm1105dvb->ts_buf, nextwrp);
> +               nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
> +       } else
> +               nbpackets = (nextwrp - oldwrp) / 188;
> +
> +       dm1105dvb->wrp = nextwrp;
> +       dvb_dmx_swfilter_packets(&dm1105dvb->demux,
> +                                       &dm1105dvb->ts_buf[oldwrp], nbpackets);
> +}
> +
>  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
>  static irqreturn_t dm1105dvb_irq(int irq, void *dev_id, struct pt_regs *regs)
>  #else
> @@ -441,11 +492,6 @@
>  #endif
>  {
>         struct dm1105dvb *dm1105dvb = dev_id;
> -       unsigned int piece;
> -       unsigned int nbpackets;
> -       u32 command;
> -       u32 nextwrp;
> -       u32 oldwrp;
>  
>         /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
>         unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
> @@ -454,48 +500,17 @@
>         switch (intsts) {
>         case INTSTS_TSIRQ:
>         case (INTSTS_TSIRQ | INTSTS_IR):
> -               nextwrp = inl(dm_io_mem(DM1105_WRP)) -
> -                       inl(dm_io_mem(DM1105_STADR)) ;
> -               oldwrp = dm1105dvb->wrp;
> -               spin_lock(&dm1105dvb->lock);
> -               if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
> -                               (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
> -                               (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
> -                       dm1105dvb->PacketErrorCount++;
> -                       /* bad packet found */
> -                       if ((dm1105dvb->PacketErrorCount >= 2) &&
> -                                       (dm1105dvb->dmarst == 0)) {
> -                               outb(1, dm_io_mem(DM1105_RST));
> -                               dm1105dvb->wrp = 0;
> -                               dm1105dvb->PacketErrorCount = 0;
> -                               dm1105dvb->dmarst = 0;
> -                               spin_unlock(&dm1105dvb->lock);
> -                               return IRQ_HANDLED;
> -                       }
> -               }
> -               if (nextwrp < oldwrp) {
> -                       piece = dm1105dvb->buffer_size - oldwrp;
> -                       memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, 
> nextwrp);
> -                       nbpackets = (piece + nextwrp)/188;
> -               } else  {
> -                       nbpackets = (nextwrp - oldwrp)/188;
> -               }
> -               dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], 
> nbpackets);
> -               dm1105dvb->wrp = nextwrp;
> -               spin_unlock(&dm1105dvb->lock);
> +               dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
> +                                       inl(dm_io_mem(DM1105_STADR));
> +               schedule_work(&dm1105dvb->work);
>                 break;
>         case INTSTS_IR:
> -               command = inl(dm_io_mem(DM1105_IRCODE));
> -               if (ir_debug)
> -                       printk("dm1105: received byte 0x%04x\n", command);
> -
> -               dm1105dvb->ir.ir_command = command;
> +               dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
>                 tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
>                 break;
>         }
> +
>         return IRQ_HANDLED;
> -
> -
>  }
>  
>  /* register with input layer */
> @@ -717,7 +732,7 @@
>  
>         dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
>         if (!dm1105dvb)
> -               goto out;
> +               return -ENOMEM;
>  
>         dm1105dvb->pdev = pdev;
>         dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
> @@ -747,13 +762,9 @@
>         spin_lock_init(&dm1105dvb->lock);
>         pci_set_drvdata(pdev, dm1105dvb);
>  
> -       ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
> +       ret = dm1105dvb_hw_init(dm1105dvb);
>         if (ret < 0)
>                 goto err_pci_iounmap;
> -
> -       ret = dm1105dvb_hw_init(dm1105dvb);
> -       if (ret < 0)
> -               goto err_free_irq;
>  
>         /* i2c */
>         i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
> @@ -820,8 +831,19 @@
>  
>         dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
>         dm1105_ir_init(dm1105dvb);
> -out:
> -       return ret;
> +
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> +       INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer, dm1105dvb);
> +#else
> +       INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
> +#endif
> +
> +       ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
> +                                               DRIVER_NAME, dm1105dvb);
> +       if (ret < 0)
> +               goto err_free_irq;
> +
> +       return 0;
>  
>  err_disconnect_frontend:
>         dmx->disconnect_frontend(dmx);
> @@ -850,7 +872,7 @@
>  err_kfree:
>         pci_set_drvdata(pdev, NULL);
>         kfree(dm1105dvb);
> -       goto out;
> +       return ret;
>  }
>  
>  static void __devexit dm1105_remove(struct pci_dev *pdev)
> [Erro ao decodificar BASE64]




Cheers,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Igor M. Liplianin Feb. 26, 2009, 4:13 p.m. UTC | #2
On 26 февраля 2009, "Igor M. Liplianin" <liplianin@tut.by> wrote:
> On Thu, 19 Feb 2009 07:18:47 +0200
>
> "Igor M. Liplianin" <liplianin@tut.by> wrote:
> > I read in mailing list about design error in dm1105.
> > So I am designer.
> > DMA buffer in the driver itself organized like ringbuffer
> > and not difficult to bind it to tasklet or work queue.
> > I choose work queue, because it is like trend :)
> > The code tested by me on quite fast computer and it works as usual.
> > I think, on slow computer difference must be noticeable.
> > The patch is preliminary.
> > Anyone can criticize.
>
> The patch looks fine for me, but, as you said this i preliminary, I'm
> marking it as RFC on patchwork. Please send me the final revision of it,
> after having a final version.
>
> Cheers,
> Mauro.
>
> > diff -r 359d95e1d541 -r f22da8d6a83c
> > linux/drivers/media/dvb/dm1105/dm1105.c ---
> > a/linux/drivers/media/dvb/dm1105/dm1105.cб═б═б═Wed Feb 18 09:49:37 2009
> > -0300 +++ b/linux/drivers/media/dvb/dm1105/dm1105.cб═б═б═Thu Feb 19
> > 04:38:32 2009 +0200 @@ -220,10 +220,14 @@
> > б═б═б═б═б═б═б═б═/* i2c */
> > б═б═б═б═б═б═б═б═struct i2c_adapter i2c_adap;
> > б═
> > +б═б═б═б═б═б═б═/* irq */
> > +б═б═б═б═б═б═б═struct work_struct work;
> > +
> > б═б═б═б═б═б═б═б═/* dma */
> > б═б═б═б═б═б═б═б═dma_addr_t dma_addr;
> > б═б═б═б═б═б═б═б═unsigned char *ts_buf;
> > б═б═б═б═б═б═б═б═u32 wrp;
> > +б═б═б═б═б═б═б═u32 nextwrp;
> > б═б═б═б═б═б═б═б═u32 buffer_size;
> > б═б═б═б═б═б═б═б═unsigned intб═б═б═б═PacketErrorCount;
> > б═б═б═б═б═б═б═б═unsigned int dmarst;
> > @@ -418,6 +422,9 @@
> > б═б═б═б═б═б═б═б═u8 data;
> > б═б═б═б═б═б═б═б═u16 keycode;
> > б═
> > +б═б═б═б═б═б═б═if (ir_debug)
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═printk(KERN_INFO "%s: received byte
> > 0x%04x\n", __func__, ircom); +
> > б═б═б═б═б═б═б═б═data = (ircom >> 8) & 0x7f;
> > б═
> > б═б═б═б═б═б═б═б═input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 <<
> > 16) | data); @@ -434,6 +441,50 @@
> > б═
> > б═}
> > б═
> > +/* work handler */
> > +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> > +static void dm1105_dmx_buffer(void *_dm1105dvb)
> > +#else
> > +static void dm1105_dmx_buffer(struct work_struct *work)
> > +#endif
> > +{
> > +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> > +б═б═б═б═б═б═б═struct dm1105dvb *dm1105dvb = _dm1105dvb;
> > +#else
> > +б═б═б═б═б═б═б═struct dm1105dvb *dm1105dvb =
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═container_
> >of(work, struct dm1105dvb, work); +#endif
> > +б═б═б═б═б═б═б═unsigned int nbpackets;
> > +б═б═б═б═б═б═б═u32 oldwrp = dm1105dvb->wrp;
> > +б═б═б═б═б═б═б═u32 nextwrp = dm1105dvb->nextwrp;
> > +
> > +б═б═б═б═б═б═б═if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═(dm1105dvb->ts_buf[oldwrp
> > + 188] == 0x47) &&
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═(dm1105dvb->ts_buf[oldwrp
> > + 188 * 2] == 0x47))) {
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->PacketErrorCount++;
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═/* bad packet found */
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═if ((dm1105dvb->PacketErrorCount >= 2) &&
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═(dm1105dvb
> >->dmarst == 0)) { +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═outb(1,
> > dm_io_mem(DM1105_RST));
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->wrp = 0;
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->PacketErrorCoun
> >t = 0; +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->dmarst =
> > 0; +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═return;
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═}
> > +б═б═б═б═б═б═б═}
> > +
> > +б═б═б═б═б═б═б═if (nextwrp < oldwrp) {
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═memcpy(dm1105dvb->ts_buf +
> > dm1105dvb->buffer_size,
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═
> >б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->ts_buf, nextwrp);
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═nbpackets = ((dm1105dvb->buffer_size -
> > oldwrp) + nextwrp) / 188; +б═б═б═б═б═б═б═} else
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═nbpackets = (nextwrp - oldwrp) / 188;
> > +
> > +б═б═б═б═б═б═б═dm1105dvb->wrp = nextwrp;
> > +б═б═б═б═б═б═б═dvb_dmx_swfilter_packets(&dm1105dvb->demux,
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═
> >б═б═б═&dm1105dvb->ts_buf[oldwrp], nbpackets); +}
> > +
> > б═#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> > б═static irqreturn_t dm1105dvb_irq(int irq, void *dev_id, struct pt_regs
> > *regs) б═#else
> > @@ -441,11 +492,6 @@
> > б═#endif
> > б═{
> > б═б═б═б═б═б═б═б═struct dm1105dvb *dm1105dvb = dev_id;
> > -б═б═б═б═б═б═б═unsigned int piece;
> > -б═б═б═б═б═б═б═unsigned int nbpackets;
> > -б═б═б═б═б═б═б═u32 command;
> > -б═б═б═б═б═б═б═u32 nextwrp;
> > -б═б═б═б═б═б═б═u32 oldwrp;
> > б═
> > б═б═б═б═б═б═б═б═/* Read-Write INSTS Ack's Interrupt for DM1105 chip
> > 16.03.2008 */ б═б═б═б═б═б═б═б═unsigned int intsts =
> > inb(dm_io_mem(DM1105_INTSTS)); @@ -454,48 +500,17 @@
> > б═б═б═б═б═б═б═б═switch (intsts) {
> > б═б═б═б═б═б═б═б═case INTSTS_TSIRQ:
> > б═б═б═б═б═б═б═б═case (INTSTS_TSIRQ | INTSTS_IR):
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═nextwrp = inl(dm_io_mem(DM1105_WRP)) -
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═inl(dm_io_mem(DM1105_STADR
> >)) ; -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═oldwrp = dm1105dvb->wrp;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═spin_lock(&dm1105dvb->lock);
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═if (!((dm1105dvb->ts_buf[oldwrp] == 0x47)
> > &&
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═(dm1105dvb
> >->ts_buf[oldwrp + 188] == 0x47) &&
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═(dm1105dvb
> >->ts_buf[oldwrp + 188 * 2] == 0x47))) {
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->PacketErrorCoun
> >t++; -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═/* bad packet found */
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═if
> > ((dm1105dvb->PacketErrorCount >= 2) &&
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═
> >б═б═б═(dm1105dvb->dmarst == 0)) {
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═outb(1,
> > dm_io_mem(DM1105_RST));
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb-
> >>wrp = 0;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb-
> >>PacketErrorCount = 0;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb-
> >>dmarst = 0;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═spin_unloc
> >k(&dm1105dvb->lock);
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═return
> > IRQ_HANDLED; -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═}
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═}
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═if (nextwrp < oldwrp) {
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═piece =
> > dm1105dvb->buffer_size - oldwrp;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═memcpy(dm1105dvb->ts_buf +
> > dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═nbpackets = (piece +
> > nextwrp)/188; -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═} elseб═б═{
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═nbpackets = (nextwrp -
> > oldwrp)/188; -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═}
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dvb_dmx_swfilter_packets(&dm1105dvb->demux
> >, &dm1105dvb->ts_buf[oldwrp], nbpackets);
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->wrp = nextwrp;
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═spin_unlock(&dm1105dvb->lock);
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->nextwrp =
> > inl(dm_io_mem(DM1105_WRP)) -
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═
> >б═б═б═inl(dm_io_mem(DM1105_STADR));
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═schedule_work(&dm1105dvb->work);
> > б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═break;
> > б═б═б═б═б═б═б═б═case INTSTS_IR:
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═command = inl(dm_io_mem(DM1105_IRCODE));
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═if (ir_debug)
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═printk("dm1105: received
> > byte 0x%04x\n", command); -
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->ir.ir_command = command;
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═dm1105dvb->ir.ir_command =
> > inl(dm_io_mem(DM1105_IRCODE));
> > б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═tasklet_schedule(&dm1105dvb->ir.ir_taskle
> >t); б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═break;
> > б═б═б═б═б═б═б═б═}
> > +
> > б═б═б═б═б═б═б═б═return IRQ_HANDLED;
> > -
> > -
> > б═}
> > б═
> > б═/* register with input layer */
> > @@ -717,7 +732,7 @@
> > б═
> > б═б═б═б═б═б═б═б═dm1105dvb = kzalloc(sizeof(struct dm1105dvb),
> > GFP_KERNEL); б═б═б═б═б═б═б═б═if (!dm1105dvb)
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═goto out;
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═return -ENOMEM;
> > б═
> > б═б═б═б═б═б═б═б═dm1105dvb->pdev = pdev;
> > б═б═б═б═б═б═б═б═dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
> > @@ -747,13 +762,9 @@
> > б═б═б═б═б═б═б═б═spin_lock_init(&dm1105dvb->lock);
> > б═б═б═б═б═б═б═б═pci_set_drvdata(pdev, dm1105dvb);
> > б═
> > -б═б═б═б═б═б═б═ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
> > DRIVER_NAME, dm1105dvb); +б═б═б═б═б═б═б═ret =
> > dm1105dvb_hw_init(dm1105dvb);
> > б═б═б═б═б═б═б═б═if (ret < 0)
> > б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═goto err_pci_iounmap;
> > -
> > -б═б═б═б═б═б═б═ret = dm1105dvb_hw_init(dm1105dvb);
> > -б═б═б═б═б═б═б═if (ret < 0)
> > -б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═goto err_free_irq;
> > б═
> > б═б═б═б═б═б═б═б═/* i2c */
> > б═б═б═б═б═б═б═б═i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
> > @@ -820,8 +831,19 @@
> > б═
> > б═б═б═б═б═б═б═б═dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
> > б═б═б═б═б═б═б═б═dm1105_ir_init(dm1105dvb);
> > -out:
> > -б═б═б═б═б═б═б═return ret;
> > +
> > +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> > +б═б═б═б═б═б═б═INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer, dm1105dvb);
> > +#else
> > +б═б═б═б═б═б═б═INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
> > +#endif
> > +
> > +б═б═б═б═б═б═б═ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═
> >б═б═б═б═б═б═б═б═б═б═б═DRIVER_NAME, dm1105dvb); +б═б═б═б═б═б═б═if (ret < 0)
> > +б═б═б═б═б═б═б═б═б═б═б═б═б═б═б═goto err_free_irq;
> > +
> > +б═б═б═б═б═б═б═return 0;
> > б═
> > б═err_disconnect_frontend:
> > б═б═б═б═б═б═б═б═dmx->disconnect_frontend(dmx);
> > @@ -850,7 +872,7 @@
> > б═err_kfree:
> > б═б═б═б═б═б═б═б═pci_set_drvdata(pdev, NULL);
> > б═б═б═б═б═б═б═б═kfree(dm1105dvb);
> > -б═б═б═б═б═б═б═goto out;
> > +б═б═б═б═б═б═б═return ret;
> > б═}
> > б═
> > б═static void __devexit dm1105_remove(struct pci_dev *pdev)
> > [Erro ao decodificar BASE64]
>
> Cheers,
> Mauro
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Today morning I sent pull request for that patch together with patch for infrared remote.
I am testing IR support for a few more cards. They will share IR codes, so that patch is needed.


Best Regards
Igor
N▀╖╡ФЛr╦⌡yЗХ ьb╡X╛╤г╖vь^√)ч╨{.nг+┴╥╔┼{╠≥Гbj)М┘ФХw*jg╛╠╗╤┴ ▌┼щ╒j/│ЙДz╧ч√┼Ю2┼ч≥╗Х╜з&╒)ъ║╚a╤зЧЬ╝G╚²Иh╝Фj:+v┴╗┼wХ├ы╔
diff mbox

Patch

diff -r 359d95e1d541 -r f22da8d6a83c linux/drivers/media/dvb/dm1105/dm1105.c
--- a/linux/drivers/media/dvb/dm1105/dm1105.c   Wed Feb 18 09:49:37 2009 -0300
+++ b/linux/drivers/media/dvb/dm1105/dm1105.c   Thu Feb 19 04:38:32 2009 +0200
@@ -220,10 +220,14 @@ 
        /* i2c */
        struct i2c_adapter i2c_adap;
 
+       /* irq */
+       struct work_struct work;
+
        /* dma */
        dma_addr_t dma_addr;
        unsigned char *ts_buf;
        u32 wrp;
+       u32 nextwrp;
        u32 buffer_size;
        unsigned int    PacketErrorCount;
        unsigned int dmarst;
@@ -418,6 +422,9 @@ 
        u8 data;
        u16 keycode;
 
+       if (ir_debug)
+               printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
+
        data = (ircom >> 8) & 0x7f;
 
        input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
@@ -434,6 +441,50 @@ 
 
 }
 
+/* work handler */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static void dm1105_dmx_buffer(void *_dm1105dvb)
+#else
+static void dm1105_dmx_buffer(struct work_struct *work)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+       struct dm1105dvb *dm1105dvb = _dm1105dvb;
+#else
+       struct dm1105dvb *dm1105dvb =
+                               container_of(work, struct dm1105dvb, work);
+#endif
+       unsigned int nbpackets;
+       u32 oldwrp = dm1105dvb->wrp;
+       u32 nextwrp = dm1105dvb->nextwrp;
+
+       if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
+                       (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
+                       (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+               dm1105dvb->PacketErrorCount++;
+               /* bad packet found */
+               if ((dm1105dvb->PacketErrorCount >= 2) &&
+                               (dm1105dvb->dmarst == 0)) {
+                       outb(1, dm_io_mem(DM1105_RST));
+                       dm1105dvb->wrp = 0;
+                       dm1105dvb->PacketErrorCount = 0;
+                       dm1105dvb->dmarst = 0;
+                       return;
+               }
+       }
+
+       if (nextwrp < oldwrp) {
+               memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
+                                               dm1105dvb->ts_buf, nextwrp);
+               nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
+       } else
+               nbpackets = (nextwrp - oldwrp) / 188;
+
+       dm1105dvb->wrp = nextwrp;
+       dvb_dmx_swfilter_packets(&dm1105dvb->demux,
+                                       &dm1105dvb->ts_buf[oldwrp], nbpackets);
+}
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
 static irqreturn_t dm1105dvb_irq(int irq, void *dev_id, struct pt_regs *regs)
 #else
@@ -441,11 +492,6 @@ 
 #endif
 {
        struct dm1105dvb *dm1105dvb = dev_id;
-       unsigned int piece;
-       unsigned int nbpackets;
-       u32 command;
-       u32 nextwrp;
-       u32 oldwrp;
 
        /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
        unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
@@ -454,48 +500,17 @@ 
        switch (intsts) {
        case INTSTS_TSIRQ:
        case (INTSTS_TSIRQ | INTSTS_IR):
-               nextwrp = inl(dm_io_mem(DM1105_WRP)) -
-                       inl(dm_io_mem(DM1105_STADR)) ;
-               oldwrp = dm1105dvb->wrp;
-               spin_lock(&dm1105dvb->lock);
-               if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
-                               (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
-                               (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
-                       dm1105dvb->PacketErrorCount++;
-                       /* bad packet found */
-                       if ((dm1105dvb->PacketErrorCount >= 2) &&
-                                       (dm1105dvb->dmarst == 0)) {
-                               outb(1, dm_io_mem(DM1105_RST));
-                               dm1105dvb->wrp = 0;
-                               dm1105dvb->PacketErrorCount = 0;
-                               dm1105dvb->dmarst = 0;
-                               spin_unlock(&dm1105dvb->lock);
-                               return IRQ_HANDLED;
-                       }
-               }
-               if (nextwrp < oldwrp) {
-                       piece = dm1105dvb->buffer_size - oldwrp;
-                       memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, 
nextwrp);
-                       nbpackets = (piece + nextwrp)/188;
-               } else  {
-                       nbpackets = (nextwrp - oldwrp)/188;
-               }
-               dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], 
nbpackets);
-               dm1105dvb->wrp = nextwrp;
-               spin_unlock(&dm1105dvb->lock);
+               dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
+                                       inl(dm_io_mem(DM1105_STADR));
+               schedule_work(&dm1105dvb->work);
                break;
        case INTSTS_IR:
-               command = inl(dm_io_mem(DM1105_IRCODE));
-               if (ir_debug)
-                       printk("dm1105: received byte 0x%04x\n", command);
-
-               dm1105dvb->ir.ir_command = command;
+               dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
                tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
                break;
        }
+
        return IRQ_HANDLED;
-
-
 }