Each comedi_subdevice uses one of the minors allocated to the
comedi subsystem. The devices used with this driver need a minimum
of 2 and a maximum of 5 subdevices.

Only allocate and initialize the number of subdevices actually needed
by the device.

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Ian Abbott <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
 drivers/staging/comedi/drivers/ni_labpc.c | 49 ++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_labpc.c 
b/drivers/staging/comedi/drivers/ni_labpc.c
index dea4cfc..1c00ed2 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -1564,6 +1564,7 @@ int labpc_common_attach(struct comedi_device *dev,
        const struct labpc_boardinfo *thisboard = comedi_board(dev);
        struct labpc_private *devpriv = dev->private;
        struct comedi_subdevice *s;
+       int subdev;
        int i;
        short lsb, msb;
        int ret;
@@ -1595,12 +1596,20 @@ int labpc_common_attach(struct comedi_device *dev,
                dev->irq = irq;
        }
 
-       ret = comedi_alloc_subdevices(dev, 5);
+       /* Only allocate the subdevices needed */
+       subdev = 1 +                    /* all boards have ai */
+                thisboard->has_ao +    /* only on some boards have ao */
+                1 +                    /* all boards have 8255 dio */
+                (thisboard->register_layout == labpc_1200_layout)
+                ? 2 : 0;               /* the calib and memory devices */
+       ret = comedi_alloc_subdevices(dev, subdev);
        if (ret)
                return ret;
 
+       subdev = 0;
+
        /* analog input subdevice */
-       s = &dev->subdevices[0];
+       s = &dev->subdevices[subdev++];
        s->type         = COMEDI_SUBD_AI;
        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
        s->n_chan       = 8;
@@ -1616,9 +1625,9 @@ int labpc_common_attach(struct comedi_device *dev,
                s->cancel       = labpc_cancel;
        }
 
-       /* analog output */
-       s = &dev->subdevices[1];
        if (thisboard->has_ao) {
+               /* analog output */
+               s = &dev->subdevices[subdev++];
                /*
                 * Could provide command support, except it only has a
                 * one sample hardware buffer for analog output and no
@@ -1639,23 +1648,19 @@ int labpc_common_attach(struct comedi_device *dev,
                        devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i));
                        devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i));
                }
-       } else {
-               s->type = COMEDI_SUBD_UNUSED;
        }
 
        /* 8255 dio */
-       s = &dev->subdevices[2];
-       /*  if board uses io memory we have to give a custom callback
-        * function to the 8255 driver */
+       s = &dev->subdevices[subdev++];
        if (thisboard->memory_mapped_io)
                subdev_8255_init(dev, s, labpc_dio_mem_callback,
                                 (unsigned long)(dev->iobase + DIO_BASE_REG));
        else
                subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG);
 
-       /*  calibration subdevices for boards that have one */
-       s = &dev->subdevices[3];
        if (thisboard->register_layout == labpc_1200_layout) {
+               /* calibration subdevice */
+               s = &dev->subdevices[subdev++];
                s->type = COMEDI_SUBD_CALIB;
                s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
                s->n_chan = 16;
@@ -1665,12 +1670,9 @@ int labpc_common_attach(struct comedi_device *dev,
 
                for (i = 0; i < s->n_chan; i++)
                        write_caldac(dev, i, s->maxdata / 2);
-       } else
-               s->type = COMEDI_SUBD_UNUSED;
 
-       /* EEPROM */
-       s = &dev->subdevices[4];
-       if (thisboard->register_layout == labpc_1200_layout) {
+               /* EEPROM */
+               s = &dev->subdevices[subdev++];
                s->type = COMEDI_SUBD_MEMORY;
                s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
                s->n_chan = EEPROM_SIZE;
@@ -1680,8 +1682,7 @@ int labpc_common_attach(struct comedi_device *dev,
 
                for (i = 0; i < EEPROM_SIZE; i++)
                        devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
-       } else
-               s->type = COMEDI_SUBD_UNUSED;
+       }
 
        return 0;
 }
@@ -1689,8 +1690,16 @@ EXPORT_SYMBOL_GPL(labpc_common_attach);
 
 void labpc_common_detach(struct comedi_device *dev)
 {
-       if (dev->subdevices)
-               subdev_8255_cleanup(dev, &dev->subdevices[2]);
+       struct comedi_subdevice *s;
+       int i;
+
+       if (dev->subdevices) {
+               for (i = 0; i < dev->n_subdevices; i++) {
+                       s = &dev->subdevices[i];
+                       if (s->type == COMEDI_SUBD_DIO)
+                               subdev_8255_cleanup(dev, s);
+               }
+       }
        if (dev->irq)
                free_irq(dev->irq, dev);
 }
-- 
1.8.1.4

_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

Reply via email to