mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 23:46:41 +07:00
V4L/DVB (10743): dm1105: not demuxing from interrupt context.
The driver already has DMA buffer organized like ringbuffer, so it is easy to switch to a work queue. Length of ringbuffer can easily be increased, if someone need it. Signed-off-by: Igor M. Liplianin <liplianin@netup.ru> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
ac40d9e098
commit
d1498ffc47
@ -220,10 +220,14 @@ struct dm1105dvb {
|
|||||||
/* i2c */
|
/* i2c */
|
||||||
struct i2c_adapter i2c_adap;
|
struct i2c_adapter i2c_adap;
|
||||||
|
|
||||||
|
/* irq */
|
||||||
|
struct work_struct work;
|
||||||
|
|
||||||
/* dma */
|
/* dma */
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
unsigned char *ts_buf;
|
unsigned char *ts_buf;
|
||||||
u32 wrp;
|
u32 wrp;
|
||||||
|
u32 nextwrp;
|
||||||
u32 buffer_size;
|
u32 buffer_size;
|
||||||
unsigned int PacketErrorCount;
|
unsigned int PacketErrorCount;
|
||||||
unsigned int dmarst;
|
unsigned int dmarst;
|
||||||
@ -415,6 +419,9 @@ static void dm1105_emit_key(unsigned long parm)
|
|||||||
u8 data;
|
u8 data;
|
||||||
u16 keycode;
|
u16 keycode;
|
||||||
|
|
||||||
|
if (ir_debug)
|
||||||
|
printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
|
||||||
|
|
||||||
data = (ircom >> 8) & 0x7f;
|
data = (ircom >> 8) & 0x7f;
|
||||||
|
|
||||||
input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
|
input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
|
||||||
@ -431,14 +438,45 @@ static void dm1105_emit_key(unsigned long parm)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* work handler */
|
||||||
|
static void dm1105_dmx_buffer(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct dm1105dvb *dm1105dvb =
|
||||||
|
container_of(work, struct dm1105dvb, work);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
|
static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct dm1105dvb *dm1105dvb = dev_id;
|
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 */
|
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
|
||||||
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
|
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
|
||||||
@ -447,48 +485,17 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
|
|||||||
switch (intsts) {
|
switch (intsts) {
|
||||||
case INTSTS_TSIRQ:
|
case INTSTS_TSIRQ:
|
||||||
case (INTSTS_TSIRQ | INTSTS_IR):
|
case (INTSTS_TSIRQ | INTSTS_IR):
|
||||||
nextwrp = inl(dm_io_mem(DM1105_WRP)) -
|
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
|
||||||
inl(dm_io_mem(DM1105_STADR)) ;
|
inl(dm_io_mem(DM1105_STADR));
|
||||||
oldwrp = dm1105dvb->wrp;
|
schedule_work(&dm1105dvb->work);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case INTSTS_IR:
|
case INTSTS_IR:
|
||||||
command = inl(dm_io_mem(DM1105_IRCODE));
|
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
|
||||||
if (ir_debug)
|
|
||||||
printk("dm1105: received byte 0x%04x\n", command);
|
|
||||||
|
|
||||||
dm1105dvb->ir.ir_command = command;
|
|
||||||
tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
|
tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register with input layer */
|
/* register with input layer */
|
||||||
@ -710,7 +717,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||||||
|
|
||||||
dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
|
dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
|
||||||
if (!dm1105dvb)
|
if (!dm1105dvb)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
dm1105dvb->pdev = pdev;
|
dm1105dvb->pdev = pdev;
|
||||||
dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
|
dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
|
||||||
@ -740,13 +747,9 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||||||
spin_lock_init(&dm1105dvb->lock);
|
spin_lock_init(&dm1105dvb->lock);
|
||||||
pci_set_drvdata(pdev, dm1105dvb);
|
pci_set_drvdata(pdev, dm1105dvb);
|
||||||
|
|
||||||
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
|
|
||||||
if (ret < 0)
|
|
||||||
goto err_pci_iounmap;
|
|
||||||
|
|
||||||
ret = dm1105dvb_hw_init(dm1105dvb);
|
ret = dm1105dvb_hw_init(dm1105dvb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_free_irq;
|
goto err_pci_iounmap;
|
||||||
|
|
||||||
/* i2c */
|
/* i2c */
|
||||||
i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
|
i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
|
||||||
@ -813,8 +816,15 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||||||
|
|
||||||
dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
|
dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
|
||||||
dm1105_ir_init(dm1105dvb);
|
dm1105_ir_init(dm1105dvb);
|
||||||
out:
|
|
||||||
return ret;
|
INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
|
||||||
|
|
||||||
|
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
|
||||||
|
DRIVER_NAME, dm1105dvb);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_free_irq;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
err_disconnect_frontend:
|
err_disconnect_frontend:
|
||||||
dmx->disconnect_frontend(dmx);
|
dmx->disconnect_frontend(dmx);
|
||||||
@ -843,7 +853,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||||||
err_kfree:
|
err_kfree:
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
kfree(dm1105dvb);
|
kfree(dm1105dvb);
|
||||||
goto out;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __devexit dm1105_remove(struct pci_dev *pdev)
|
static void __devexit dm1105_remove(struct pci_dev *pdev)
|
||||||
|
Loading…
Reference in New Issue
Block a user