staging: comedi: comedi_bond: don't map channels individually
authorIan Abbott <abbotti@mev.co.uk>
Fri, 23 Aug 2013 13:45:03 +0000 (14:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Aug 2013 13:41:56 +0000 (06:41 -0700)
The private data structure (`struct comedi_bond_private`) for the
overall "comedi_bond" device maps each channel individually to a pointer
to the `struct bonded_device` it belongs to via array member
`chan_id_dev_map[MAX_CHANS]`. This speeds up look-ups from channel
number to bonded device a bit, but the length of the array used to look
this up is currently fixed at `MAX_CHANS` (256) and there are no
overflow checks when filling the array.

In practice, there will only be a few bonded devices (actually bonded
subdevices) and it is practical to just skip through the list until we
reach the one containing the desired channel.

The only place where the bonded device is looked up from the channel
number is in `bonding_dio_insn_config()`.  Change it to do the look-up
by skipping through the list of bonded devices and remove the
`chan_id_dev_map[]` member.  The `chanid_offset` member of `struct
bonded_device` is also no longer needed as the value can be derived
while skipping through the list of bonded devices, so remove that member
as well.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/comedi_bond.c

index c0a427cab9dbdd3ce2ccfde8a1f38683c6233641..493fdb7dee504feeeb78df598d8d605c101ca676 100644 (file)
 #include "../comedilib.h"
 #include "../comedidev.h"
 
-/* The maxiumum number of channels per subdevice. */
-#define MAX_CHANS 256
-
 struct bonded_device {
        struct comedi_device *dev;
        unsigned minor;
        unsigned subdev;
        unsigned subdev_type;
        unsigned nchans;
-       unsigned chanid_offset; /* The offset into our unified linear
-                                * channel-id's of chanid 0 on this
-                                * subdevice. */
 };
 
 struct comedi_bond_private {
@@ -72,7 +66,6 @@ struct comedi_bond_private {
        char name[MAX_BOARD_NAME];
        struct bonded_device **devs;
        unsigned ndevs;
-       struct bonded_device *chan_id_dev_map[MAX_CHANS];
        unsigned nchans;
 };
 
@@ -133,12 +126,22 @@ static int bonding_dio_insn_config(struct comedi_device *dev,
 {
        struct comedi_bond_private *devpriv = dev->private;
        int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+       unsigned int chanid_offset;
        unsigned int io;
        struct bonded_device *bdev;
+       struct bonded_device **devs;
 
        if (chan < 0 || chan >= devpriv->nchans)
                return -EINVAL;
-       bdev = devpriv->chan_id_dev_map[chan];
+
+       /*
+        * Locate bonded subdevice.
+        */
+       chanid_offset = 0;
+       devs = devpriv->devs;
+       for (bdev = *devs++; chan >= chanid_offset + bdev->nchans;
+            bdev = *devs++)
+               chanid_offset += bdev->nchans;
 
        /*
         * The input or output configuration of each digital line is
@@ -165,7 +168,7 @@ static int bonding_dio_insn_config(struct comedi_device *dev,
                break;
        }
        /* 'real' channel id for this subdev.. */
-       chan -= bdev->chanid_offset;
+       chan -= chanid_offset;
        ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io);
        if (ret != 1)
                return -EINVAL;
@@ -252,12 +255,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
                        bdev->subdev = sdev;
                        bdev->subdev_type = COMEDI_SUBD_DIO;
                        bdev->nchans = nchans;
-                       bdev->chanid_offset = devpriv->nchans;
-
-                       /* map channel id's to bonded_device * pointer.. */
-                       while (nchans--)
-                               devpriv->chan_id_dev_map[devpriv->nchans++] =
-                                   bdev;
+                       devpriv->nchans += nchans;
 
                        /*
                         * Now put bdev pointer at end of devpriv->devs array