[PATCH 28/48] staging: comedi: pcmmio: unwind the digital i/o subdevice init

H Hartley Sweeten hsweeten at visionengravers.com
Mon Dec 9 22:31:04 UTC 2013


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 at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 drivers/staging/comedi/drivers/pcmmio.c | 134 +++++++++++---------------------
 1 file changed, 45 insertions(+), 89 deletions(-)

diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 4da5e58..7026ebc 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -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;
-
-		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;
-
-		/* 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;
-			}
-
-			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);
-
-		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 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;
+
+	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;
+
+	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;
+
+	spin_lock_init(&subpriv->dio.intr.spinlock);
+
+	/* 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);
 
-- 
1.8.4.4



More information about the devel mailing list