Re: dm1105: not demuxing from interrupt context
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
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