diff options
author | Daniel Scheller <d.scheller@gmx.net> | 2018-04-09 18:47:40 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-05-04 16:34:04 +0200 |
commit | 1dda87ac151034f74010818e2fb8637e7ee7f02d (patch) | |
tree | 528b606f5eec41536693e51a13cb06bee308eec8 /drivers/media/pci | |
parent | media: ddbridge: request/free_irq using pci_irq_vector, enable MSI-X (diff) | |
download | linux-1dda87ac151034f74010818e2fb8637e7ee7f02d.tar.xz linux-1dda87ac151034f74010818e2fb8637e7ee7f02d.zip |
media: ddbridge: add helper for IRQ handler setup
Introduce the ddb_irq_set() helper function (along with a matching
prototype in ddbridge.h) to improve the set up of the IRQ handlers
and handler_data, and rework storing this data into the ddb_link
using a new ddb_irq struct. This also does the necessary rework
of affected variables. And while at it, always do queue_work in
input_handler() as there's not much of a difference to directly
calling input_work if there's no ptr at input->redi, or queueing
this call.
Picked up from the upstream dddvb-0.9.33 release.
Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/pci')
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge-core.c | 53 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge-i2c.c | 5 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge.h | 11 |
3 files changed, 41 insertions, 28 deletions
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index ea34f1495599..707a479e7b18 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -108,6 +108,16 @@ static struct ddb *ddbs[DDB_MAX_ADAPTER]; /****************************************************************************/ /****************************************************************************/ +struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr, + void (*handler)(void *), void *data) +{ + struct ddb_irq *irq = &dev->link[link].irq[nr]; + + irq->handler = handler; + irq->data = data; + return irq; +} + static void ddb_set_dma_table(struct ddb_io *io) { struct ddb *dev = io->port->dev; @@ -2094,26 +2104,18 @@ static void input_work(struct work_struct *work) spin_unlock_irqrestore(&dma->lock, flags); } -static void input_handler(unsigned long data) +static void input_handler(void *data) { struct ddb_input *input = (struct ddb_input *)data; struct ddb_dma *dma = input->dma; - /* - * If there is no input connected, input_tasklet() will - * just copy pointers and ACK. So, there is no need to go - * through the tasklet scheduler. - */ - if (input->redi) - queue_work(ddb_wq, &dma->work); - else - input_work(&dma->work); + queue_work(ddb_wq, &dma->work); } -static void output_handler(unsigned long data) +static void output_work(struct work_struct *work) { - struct ddb_output *output = (struct ddb_output *)data; - struct ddb_dma *dma = output->dma; + struct ddb_dma *dma = container_of(work, struct ddb_dma, work); + struct ddb_output *output = (struct ddb_output *)dma->io; struct ddb *dev = output->port->dev; spin_lock(&dma->lock); @@ -2129,6 +2131,14 @@ static void output_handler(unsigned long data) spin_unlock(&dma->lock); } +static void output_handler(void *data) +{ + struct ddb_output *output = (struct ddb_output *)data; + struct ddb_dma *dma = output->dma; + + queue_work(ddb_wq, &dma->work); +} + /****************************************************************************/ /****************************************************************************/ @@ -2159,6 +2169,7 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out) spin_lock_init(&dma->lock); init_waitqueue_head(&dma->wq); if (out) { + INIT_WORK(&dma->work, output_work); dma->regs = rm->odma->base + rm->odma->size * nr; dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr; dma->num = OUTPUT_DMA_BUFS; @@ -2203,8 +2214,7 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr) dev_dbg(dev->dev, "init link %u, input %u, handler %u\n", port->lnr, nr, dma_nr + base); - dev->handler[0][dma_nr + base] = input_handler; - dev->handler_data[0][dma_nr + base] = (unsigned long)input; + ddb_irq_set(dev, 0, dma_nr + base, &input_handler, input); ddb_dma_init(input, dma_nr, 0); } } @@ -2229,8 +2239,7 @@ static void ddb_output_init(struct ddb_port *port, int nr) const struct ddb_regmap *rm0 = io_regmap(output, 0); u32 base = rm0->irq_base_odma; - dev->handler[0][nr + base] = output_handler; - dev->handler_data[0][nr + base] = (unsigned long)output; + ddb_irq_set(dev, 0, nr + base, &output_handler, output); ddb_dma_init(output, nr, 1); } } @@ -2374,8 +2383,9 @@ void ddb_ports_release(struct ddb *dev) /****************************************************************************/ #define IRQ_HANDLE(_nr) \ - do { if ((s & (1UL << ((_nr) & 0x1f))) && dev->handler[0][_nr]) \ - dev->handler[0][_nr](dev->handler_data[0][_nr]); } \ + do { if ((s & (1UL << ((_nr) & 0x1f))) && \ + dev->link[0].irq[_nr].handler) \ + dev->link[0].irq[_nr].handler(dev->link[0].irq[_nr].data); } \ while (0) static void irq_handle_msg(struct ddb *dev, u32 s) @@ -3186,7 +3196,7 @@ static void tempmon_setfan(struct ddb_link *link) ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL); } -static void temp_handler(unsigned long data) +static void temp_handler(void *data) { struct ddb_link *link = (struct ddb_link *)data; @@ -3209,8 +3219,7 @@ static int tempmon_init(struct ddb_link *link, int first_time) memcpy(link->temp_tab, temperature_table, sizeof(temperature_table)); } - dev->handler[l][link->info->tempmon_irq] = temp_handler; - dev->handler_data[l][link->info->tempmon_irq] = (unsigned long)link; + ddb_irq_set(dev, l, link->info->tempmon_irq, temp_handler, link); ddblwritel(link, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN | TEMPMON_CONTROL_INTENABLE), TEMPMON_CONTROL); diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c index 82a9a0e806fc..667340c86ea7 100644 --- a/drivers/media/pci/ddbridge/ddbridge-i2c.c +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c @@ -147,7 +147,7 @@ void ddb_i2c_release(struct ddb *dev) } } -static void i2c_handler(unsigned long priv) +static void i2c_handler(void *priv) { struct ddb_i2c *i2c = (struct ddb_i2c *)priv; @@ -210,8 +210,7 @@ int ddb_i2c_init(struct ddb *dev) if (!(dev->link[l].info->i2c_mask & (1 << i))) continue; i2c = &dev->i2c[num]; - dev->handler_data[l][i + base] = (unsigned long)i2c; - dev->handler[l][i + base] = i2c_handler; + ddb_irq_set(dev, l, i + base, i2c_handler, i2c); stat = ddb_i2c_add(dev, i2c, regmap, l, i, num); if (stat) break; diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index dbd5f551ce76..de9ddf1068bf 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -305,6 +305,11 @@ struct ddb_lnb { u32 fmode; }; +struct ddb_irq { + void (*handler)(void *); + void *data; +}; + struct ddb_link { struct ddb *dev; const struct ddb_info *info; @@ -319,6 +324,7 @@ struct ddb_link { spinlock_t temp_lock; /* lock temp chip access */ int overtemperature_error; u8 temp_tab[11]; + struct ddb_irq irq[256]; }; struct ddb { @@ -343,9 +349,6 @@ struct ddb { struct ddb_dma idma[DDB_MAX_INPUT]; struct ddb_dma odma[DDB_MAX_OUTPUT]; - void (*handler[4][256])(unsigned long); - unsigned long handler_data[4][256]; - struct device *ddb_dev; u32 ddb_dev_users; u32 nr; @@ -369,6 +372,8 @@ int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len); /****************************************************************************/ /* ddbridge-core.c */ +struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr, + void (*handler)(void *), void *data); void ddb_ports_detach(struct ddb *dev); void ddb_ports_release(struct ddb *dev); void ddb_buffers_free(struct ddb *dev); |