staging: comedi: pcmmio: unwind the digital i/o subdevice init

The board supported by this driver only has one asic that provides the
two digital i/o subdevices. The first dio subdevice has 24 channels that
support interrupts. The second dio subdevice also has 24 channels but no
interrupt support.

To make the code clearer and easier to maintain, remove the for () loop
that initialized these subdevices.

Also, correctly initialize the interrupt subdevice. The current code does
not set the SDF_CMD_READ subdev_flag and does not set the dev->read_subdev
pointer in the comedi_device.

Use the dev->read_subdev pointer in the interrupt handler to get the
interrupt subdevice and private data pointer instead of searching for
them. To keep this patch reviewable, the extra indents in interrupt_pcmmio()
will be removed later.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
H Hartley Sweeten 2013-12-09 15:31:04 -07:00 committed by Greg Kroah-Hartman
parent 29947fd631
commit 19e0bf1235

View File

@ -398,10 +398,11 @@ static void pcmmio_stop_intr(struct comedi_device *dev,
static irqreturn_t interrupt_pcmmio(int irq, void *d)
{
int asic, got1 = 0;
struct comedi_device *dev = (struct comedi_device *)d;
struct comedi_device *dev = d;
struct pcmmio_private *devpriv = dev->private;
int i;
struct comedi_subdevice *s = dev->read_subdev;
struct pcmmio_subdev_private *subpriv = s->private;
int asic, got1 = 0;
for (asic = 0; asic < MAX_ASICS; ++asic) {
if (irq == dev->irq) {
@ -447,19 +448,10 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
spin_unlock_irqrestore(&devpriv->pagelock, flags);
if (triggered) {
struct comedi_subdevice *s;
/*
* TODO here: dispatch io lines to subdevs
* with commands..
*/
dev_dbg(dev->class_dev,
"got edge detect interrupt %d asic %d which_chans: %06x\n",
irq, asic, triggered);
for (i = 2; i < dev->n_subdevices; i++) {
struct pcmmio_subdev_private *subpriv;
s = &dev->subdevices[i];
subpriv = s->private;
/*
* this is an interrupt subdev,
* and it matches this asic!
@ -545,7 +537,6 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
}
}
}
}
@ -927,8 +918,6 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct pcmmio_private *devpriv;
struct pcmmio_subdev_private *subpriv;
struct comedi_subdevice *s;
int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
thisasic_chanct = 0;
int ret;
ret = comedi_request_region(dev, it->options[0], 32);
@ -941,16 +930,12 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
spin_lock_init(&devpriv->pagelock);
chans_left = CHANS_PER_ASIC * 1;
n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
n_subdevs = n_dio_subdevs + 2;
devpriv->sprivs =
kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
GFP_KERNEL);
devpriv->sprivs = kcalloc(4, sizeof(struct pcmmio_subdev_private),
GFP_KERNEL);
if (!devpriv->sprivs)
return -ENOMEM;
ret = comedi_alloc_subdevices(dev, n_subdevs);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
@ -983,73 +968,44 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(0, dev->iobase + PCMMIO_AO_2ND_DAC_OFFSET +
PCMMIO_AO_RESOURCE_ENA_REG);
port = 0;
asic = 0;
for (sdev_no = 2; sdev_no < dev->n_subdevices; ++sdev_no) {
int byte_no;
/* Digital I/O subdevice with interrupt support */
s = &dev->subdevices[2];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
s->maxdata = 1;
s->len_chanlist = 1;
s->range_table = &range_digital;
s->insn_bits = pcmmio_dio_insn_bits;
s->insn_config = pcmmio_dio_insn_config;
s = &dev->subdevices[sdev_no];
subpriv = &devpriv->sprivs[sdev_no];
s->private = subpriv;
s->maxdata = 1;
s->range_table = &range_digital;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->type = COMEDI_SUBD_DIO;
s->insn_bits = pcmmio_dio_insn_bits;
s->insn_config = pcmmio_dio_insn_config;
s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
subpriv->dio.intr.asic = -1;
subpriv->dio.intr.first_chan = -1;
subpriv->dio.intr.asic_chan = -1;
subpriv->dio.intr.num_asic_chans = -1;
subpriv->dio.intr.active = 0;
s->len_chanlist = 1;
dev->read_subdev = s;
s->subdev_flags |= SDF_CMD_READ;
s->len_chanlist = s->n_chan;
s->cancel = pcmmio_cancel;
s->do_cmd = pcmmio_cmd;
s->do_cmdtest = pcmmio_cmdtest;
/* save the ioport address for each 'port' of 8 channels in the
subdevice */
for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
if (port >= PORTS_PER_ASIC) {
port = 0;
++asic;
thisasic_chanct = 0;
}
s->private = &devpriv->sprivs[2];
subpriv = s->private;
subpriv->dio.intr.asic = 0;
subpriv->dio.intr.active = 0;
subpriv->dio.intr.stop_count = 0;
subpriv->dio.intr.first_chan = 0;
subpriv->dio.intr.asic_chan = 0;
subpriv->dio.intr.num_asic_chans = 24;
if (thisasic_chanct <
CHANS_PER_PORT * INTR_PORTS_PER_ASIC
&& subpriv->dio.intr.asic < 0) {
/*
* this is an interrupt subdevice,
* so setup the struct
*/
subpriv->dio.intr.asic = asic;
subpriv->dio.intr.active = 0;
subpriv->dio.intr.stop_count = 0;
subpriv->dio.intr.first_chan = byte_no * 8;
subpriv->dio.intr.asic_chan = thisasic_chanct;
subpriv->dio.intr.num_asic_chans =
s->n_chan - subpriv->dio.intr.first_chan;
s->cancel = pcmmio_cancel;
s->do_cmd = pcmmio_cmd;
s->do_cmdtest = pcmmio_cmdtest;
s->len_chanlist =
subpriv->dio.intr.num_asic_chans;
}
thisasic_chanct += CHANS_PER_PORT;
}
spin_lock_init(&subpriv->dio.intr.spinlock);
spin_lock_init(&subpriv->dio.intr.spinlock);
chans_left -= s->n_chan;
if (!chans_left) {
/*
* reset the asic to our first asic,
* to do intr subdevs
*/
asic = 0;
port = 0;
}
}
/* Digital I/O subdevice */
s = &dev->subdevices[3];
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = pcmmio_dio_insn_bits;
s->insn_config = pcmmio_dio_insn_config;
pcmmio_reset(dev);