Re: dm1105: not demuxing from interrupt context

2009-02-26 Thread Mauro Carvalho Chehab
On Thu, 19 Feb 2009 07:18:47 +0200
Igor M. Liplianin liplia...@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 intPacketErrorCount;
 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, (0xf8  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 

Re: dm1105: not demuxing from interrupt context

2009-02-26 Thread Igor M. Liplianin
On 26 февраля 2009, Igor M. Liplianin liplia...@tut.by wrote:
 On Thu, 19 Feb 2009 07:18:47 +0200

 Igor M. Liplianin liplia...@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, (0xf8 
  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