1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

add ddb_irq_set to set irq handlers

always use tasklet/workqueue for input/ouput handlers
This commit is contained in:
Ralph Metzler 2017-10-25 23:03:16 +02:00
parent a385bcb70c
commit b7c9038f51
4 changed files with 77 additions and 62 deletions

View File

@ -91,6 +91,16 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data)
{
struct ddb_irq *irq = &dev->link[0].irq[nr];
irq->handler = handler;
irq->data = data;
return irq;
}
static void ddb_set_dma_table(struct ddb_io *io) static void ddb_set_dma_table(struct ddb_io *io)
{ {
struct ddb *dev = io->port->dev; struct ddb *dev = io->port->dev;
@ -2307,13 +2317,12 @@ static void input_write_dvb(struct ddb_input *input,
static void input_work(struct work_struct *work) static void input_work(struct work_struct *work)
{ {
struct ddb_dma *dma = container_of(work, struct ddb_dma, work); struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
struct ddb_input *input = (struct ddb_input *)dma->io;
#else #else
static void input_tasklet(unsigned long data) static void input_tasklet(unsigned long data)
{ {
struct ddb_input *input = (struct ddb_input *)data; struct ddb_dma *dma = (struct ddb_dma *)data;
struct ddb_dma *dma = input->dma;
#endif #endif
struct ddb_input *input = (struct ddb_input *)dma->io;
struct ddb *dev = input->port->dev; struct ddb *dev = input->port->dev;
unsigned long flags; unsigned long flags;
@ -2337,32 +2346,28 @@ static void input_tasklet(unsigned long data)
spin_unlock_irqrestore(&dma->lock, flags); 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_input *input = (struct ddb_input *)data;
struct ddb_dma *dma = input->dma; 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.
*/
#ifdef DDB_USE_WORK #ifdef DDB_USE_WORK
if (input->redi) queue_work(ddb_wq, &dma->work);
queue_work(ddb_wq, &dma->work);
else
input_work(&dma->work);
#else #else
if (input->redi) input_tasklet(dma);
tasklet_schedule(&dma->tasklet);
else
input_tasklet(data);
#endif #endif
} }
static void output_handler(unsigned long data) #ifdef DDB_USE_WORK
static void output_work(struct work_struct *work)
{ {
struct ddb_output *output = (struct ddb_output *)data; struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
struct ddb_dma *dma = output->dma; #else
static void output_tasklet(unsigned long data)
{
struct ddb_dma *dma = (struct ddb_output *)data;
#endif
struct ddb_output *output = (struct ddb_output *)dma->io;
struct ddb *dev = output->port->dev; struct ddb *dev = output->port->dev;
spin_lock(&dma->lock); spin_lock(&dma->lock);
@ -2378,6 +2383,18 @@ static void output_handler(unsigned long data)
spin_unlock(&dma->lock); spin_unlock(&dma->lock);
} }
static void output_handler(void *data)
{
struct ddb_output *output = (struct ddb_output *)data;
struct ddb_dma *dma = output->dma;
#ifdef DDB_USE_WORK
queue_work(ddb_wq, &dma->work);
#else
tasklet_schedule(&dma->tasklet);
#endif
}
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
@ -2394,7 +2411,7 @@ static const struct ddb_regmap *io_regmap(struct ddb_io *io, int link)
return info->regmap; return info->regmap;
} }
static void ddb_dma_init(struct ddb_io *io, int nr, int out) static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
{ {
struct ddb_dma *dma; struct ddb_dma *dma;
const struct ddb_regmap *rm = io_regmap(io, 0); const struct ddb_regmap *rm = io_regmap(io, 0);
@ -2405,6 +2422,11 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out)
spin_lock_init(&dma->lock); spin_lock_init(&dma->lock);
init_waitqueue_head(&dma->wq); init_waitqueue_head(&dma->wq);
if (out) { if (out) {
#ifdef DDB_USE_WORK
INIT_WORK(&dma->work, output_work);
#else
tasklet_init(&dma->tasklet, output_tasklet, (unsigned long)dma);
#endif
dma->regs = rm->odma->base + rm->odma->size * nr; dma->regs = rm->odma->base + rm->odma->size * nr;
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr; dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
if (io->port->dev->link[0].info->type == DDB_MOD && if (io->port->dev->link[0].info->type == DDB_MOD &&
@ -2421,7 +2443,7 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out)
#ifdef DDB_USE_WORK #ifdef DDB_USE_WORK
INIT_WORK(&dma->work, input_work); INIT_WORK(&dma->work, input_work);
#else #else
tasklet_init(&dma->tasklet, input_tasklet, (unsigned long)io); tasklet_init(&dma->tasklet, input_tasklet, (unsigned long)dma);
#endif #endif
dma->regs = rm->idma->base + rm->idma->size * nr; dma->regs = rm->idma->base + rm->idma->size * nr;
dma->bufregs = rm->idma_buf->base + rm->idma_buf->size * nr; dma->bufregs = rm->idma_buf->base + rm->idma_buf->size * nr;
@ -2458,9 +2480,8 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
dev_info(dev->dev, "init link %u, input %u, handler %u\n", dev_info(dev->dev, "init link %u, input %u, handler %u\n",
port->lnr, nr, dma_nr + base); port->lnr, nr, dma_nr + base);
dev->handler[0][dma_nr + base] = input_handler; ddb_irq_set(dev, 0, dma_nr + base, &input_handler, input);
dev->handler_data[0][dma_nr + base] = (unsigned long)input; ddb_dma_init(input, dma_nr, 0, dma_nr + base);
ddb_dma_init(input, dma_nr, 0);
} }
} }
@ -2482,9 +2503,8 @@ static void ddb_output_init(struct ddb_port *port, int nr)
const struct ddb_regmap *rm0 = io_regmap(output, 0); const struct ddb_regmap *rm0 = io_regmap(output, 0);
u32 base = rm0->irq_base_odma; u32 base = rm0->irq_base_odma;
dev->handler[0][nr + base] = output_handler; ddb_irq_set(dev, 0, nr + base, &output_handler, output);
dev->handler_data[0][nr + base] = (unsigned long)output; ddb_dma_init(output, nr, 1, nr + base);
ddb_dma_init(output, nr, 1);
} }
} }
@ -2597,10 +2617,9 @@ static void ddb_ports_init(struct ddb *dev)
break; break;
case DDB_MOD: case DDB_MOD:
ddb_output_init(port, i); ddb_output_init(port, i);
dev->handler[0][i + rm->irq_base_rate] = ddb_irq_set(dev, 0, i + rm->irq_base_rate,
ddbridge_mod_rate_handler; &ddbridge_mod_rate_handler,
dev->handler_data[0][i + rm->irq_base_rate] = &dev->output[i]);
(unsigned long)&dev->output[i];
break; break;
default: default:
break; break;
@ -2640,8 +2659,8 @@ void ddb_ports_release(struct ddb *dev)
/****************************************************************************/ /****************************************************************************/
#define IRQ_HANDLE(_n) \ #define IRQ_HANDLE(_n) \
do { if ((s & (1UL << ((_n) & 0x1f))) && dev->handler[0][_n]) \ do { if ((s & (1UL << ((_n) & 0x1f))) && dev->link[0].irq[_n].handler) \
dev->handler[0][_n](dev->handler_data[0][_n]); } \ dev->link[0].irq[_n].handler(dev->link[0].irq[_n].data); } \
while (0) while (0)
#define IRQ_HANDLE_BYTE(_shift) { \ #define IRQ_HANDLE_BYTE(_shift) { \
@ -4158,11 +4177,11 @@ void ddb_device_destroy(struct ddb *dev)
} }
#define LINK_IRQ_HANDLE(_l, _nr) \ #define LINK_IRQ_HANDLE(_l, _nr) \
do { if ((s & (1UL << (_nr))) && dev->handler[_l][_nr]) \ do { if ((s & (1UL << (_nr))) && dev->link[_l].irq[_nr].handler) \
dev->handler[_l][_nr](dev->handler_data[_l][_nr]); } \ dev->link[_l].irq[_nr].handler(dev->link[_l].irq[_nr].data); } \
while (0) while (0)
static void gtl_link_handler(unsigned long priv) static void gtl_link_handler(void *priv)
{ {
struct ddb *dev = (struct ddb *)priv; struct ddb *dev = (struct ddb *)priv;
u32 regs = dev->link[0].info->regmap->gtl->base; u32 regs = dev->link[0].info->regmap->gtl->base;
@ -4191,7 +4210,7 @@ static void link_tasklet(unsigned long data)
LINK_IRQ_HANDLE(l, 24); LINK_IRQ_HANDLE(l, 24);
} }
static void gtl_irq_handler(unsigned long priv) static void gtl_irq_handler(void *priv)
{ {
struct ddb_link *link = (struct ddb_link *)priv; struct ddb_link *link = (struct ddb_link *)priv;
#if 1 #if 1
@ -4251,16 +4270,13 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
link->info->type != DDB_OCTOPUS_MAX) { link->info->type != DDB_OCTOPUS_MAX) {
dev_info(dev->dev, dev_info(dev->dev,
"Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.", "Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.",
id); id);
return -1; return -1;
} }
link->ids.devid = id; link->ids.devid = id;
ddbwritel(dev, 1, regs + 0x20); ddbwritel(dev, 1, regs + 0x20);
ddb_irq_set(dev, 0, base + l, gtl_irq_handler, link);
dev->handler_data[0][base + l] = (unsigned long)link;
dev->handler[0][base + l] = gtl_irq_handler;
dev->link[l].ids.hwid = ddbreadl(dev, DDB_LINK_TAG(l) | 0); dev->link[l].ids.hwid = ddbreadl(dev, DDB_LINK_TAG(l) | 0);
dev->link[l].ids.regmapid = ddbreadl(dev, DDB_LINK_TAG(l) | 4); dev->link[l].ids.regmapid = ddbreadl(dev, DDB_LINK_TAG(l) | 4);
dev->link[l].ids.vendor = id & 0xffff; dev->link[l].ids.vendor = id & 0xffff;
@ -4287,8 +4303,7 @@ static int ddb_gtl_init(struct ddb *dev)
{ {
u32 l, base = dev->link[0].info->regmap->irq_base_gtl; u32 l, base = dev->link[0].info->regmap->irq_base_gtl;
dev->handler_data[0][base] = (unsigned long)dev; ddb_irq_set(dev, 0, base, gtl_link_handler, dev);
dev->handler[0][base] = gtl_link_handler;
for (l = 1; l < dev->link[0].info->regmap->gtl->num + 1; l++) for (l = 1; l < dev->link[0].info->regmap->gtl->num + 1; l++)
ddb_gtl_init_link(dev, l); ddb_gtl_init_link(dev, l);
return 0; return 0;
@ -4330,7 +4345,7 @@ static void tempmon_setfan(struct ddb_link *link)
ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL); 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; struct ddb_link *link = (struct ddb_link *)data;
@ -4353,8 +4368,7 @@ static int tempmon_init(struct ddb_link *link, int first_time)
memcpy(link->temp_tab, temperature_table, memcpy(link->temp_tab, temperature_table,
sizeof(temperature_table)); sizeof(temperature_table));
} }
dev->handler[l][link->info->tempmon_irq] = temp_handler; ddb_irq_set(dev, l, link->info->tempmon_irq, temp_handler, link);
dev->handler_data[l][link->info->tempmon_irq] = (unsigned long)link;
ddblwritel(link, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN | ddblwritel(link, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN |
TEMPMON_CONTROL_INTENABLE), TEMPMON_CONTROL_INTENABLE),
TEMPMON_CONTROL); TEMPMON_CONTROL);

View File

@ -137,7 +137,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; struct ddb_i2c *i2c = (struct ddb_i2c *)priv;
@ -199,8 +199,7 @@ int ddb_i2c_init(struct ddb *dev)
if (!(dev->link[l].info->i2c_mask & (1 << i))) if (!(dev->link[l].info->i2c_mask & (1 << i)))
continue; continue;
i2c = &dev->i2c[num]; i2c = &dev->i2c[num];
dev->handler_data[l][i + base] = (unsigned long)i2c; ddb_irq_set(dev, l, i + base, i2c_handler, i2c);
dev->handler[l][i + base] = i2c_handler;
stat = ddb_i2c_add(dev, i2c, regmap, l, i, num); stat = ddb_i2c_add(dev, i2c, regmap, l, i, num);
if (stat) if (stat)
break; break;

View File

@ -434,7 +434,7 @@ static u32 max2871_sdr[6] = {
0x007A8098, 0x600080C9, 0x510061C2, 0x010000CB, 0x6199003C, 0x60440005 0x007A8098, 0x600080C9, 0x510061C2, 0x010000CB, 0x6199003C, 0x60440005
}; };
static void lostlock_handler(unsigned long data) static void lostlock_handler(void *data)
{ {
struct ddb *dev = (struct ddb *)data; struct ddb *dev = (struct ddb *)data;
@ -477,12 +477,9 @@ static int mod_setup_max2871(struct ddb *dev, u32 *reg)
ddbwritel(dev, ddbwritel(dev,
MAX2871_CONTROL_CE | MAX2871_CONTROL_LOSTLOCK, MAX2871_CONTROL_CE | MAX2871_CONTROL_LOSTLOCK,
MAX2871_CONTROL); MAX2871_CONTROL);
if (dev->link[0].info->lostlock_irq) { if (dev->link[0].info->lostlock_irq)
dev->handler_data[0][dev->link[0].info->lostlock_irq] = ddb_irq_set(dev, 0, dev->link[0].info->lostlock_irq,
(unsigned long)dev; lostlock_handler, dev);
dev->handler[0][dev->link[0].info->lostlock_irq] =
lostlock_handler;
}
} }
return status; return status;
} }
@ -1263,7 +1260,7 @@ fail:
* 27000000 * 1504 * 2^22 / (6900000 * 188 / 204) = 26785190066.1 * 27000000 * 1504 * 2^22 / (6900000 * 188 / 204) = 26785190066.1
*/ */
void ddbridge_mod_rate_handler(unsigned long data) void ddbridge_mod_rate_handler(void *data)
{ {
struct ddb_output *output = (struct ddb_output *) data; struct ddb_output *output = (struct ddb_output *) data;
struct ddb_dma *dma = output->dma; struct ddb_dma *dma = output->dma;

View File

@ -392,6 +392,11 @@ struct ddb_lnb {
u32 fmode; u32 fmode;
}; };
struct ddb_irq {
void (*handler)(void *);
void *data;
};
struct ddb_link { struct ddb_link {
struct ddb *dev; struct ddb *dev;
const struct ddb_info *info; const struct ddb_info *info;
@ -406,6 +411,7 @@ struct ddb_link {
spinlock_t temp_lock; /* lock temp chip access */ spinlock_t temp_lock; /* lock temp chip access */
int over_temperature_error; int over_temperature_error;
u8 temp_tab[11]; u8 temp_tab[11];
struct ddb_irq irq[256];
}; };
struct ddb { struct ddb {
@ -431,9 +437,6 @@ struct ddb {
struct ddb_dma idma[DDB_MAX_INPUT]; struct ddb_dma idma[DDB_MAX_INPUT];
struct ddb_dma odma[DDB_MAX_OUTPUT]; struct ddb_dma odma[DDB_MAX_OUTPUT];
void (*handler[4][256])(unsigned long);
unsigned long handler_data[4][256];
struct device *ddb_dev; struct device *ddb_dev;
u32 ddb_dev_users; u32 ddb_dev_users;
u32 nr; u32 nr;
@ -524,7 +527,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
int ddbridge_mod_init(struct ddb *dev); int ddbridge_mod_init(struct ddb *dev);
void ddbridge_mod_output_stop(struct ddb_output *output); void ddbridge_mod_output_stop(struct ddb_output *output);
int ddbridge_mod_output_start(struct ddb_output *output); int ddbridge_mod_output_start(struct ddb_output *output);
void ddbridge_mod_rate_handler(unsigned long data); void ddbridge_mod_rate_handler(void *);
void ddb_device_destroy(struct ddb *dev); void ddb_device_destroy(struct ddb *dev);
void ddb_nsd_detach(struct ddb *dev); void ddb_nsd_detach(struct ddb *dev);
@ -549,4 +552,6 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate);
int ddb_fe_attach_mxl5xx(struct ddb_input *input); int ddb_fe_attach_mxl5xx(struct ddb_input *input);
int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm); int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm);
struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data);
#endif #endif