--- /dev/null
+From abbotti@mev.co.uk Thu Oct 10 15:53:41 2013
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Thu, 10 Oct 2013 10:53:46 +0100
+Subject: staging: comedi: ni_65xx: (bug fix) confine insn_bits to one subdevice
+To: stable@vger.kernel.org
+Cc: Ian Abbott <abbotti@mev.co.uk>
+Message-ID: <1381398826-12693-1-git-send-email-abbotti@mev.co.uk>
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 677a31565692d596ef42ea589b53ba289abf4713 upstream.
+
+The `insn_bits` handler `ni_65xx_dio_insn_bits()` has a `for` loop that
+currently writes (optionally) and reads back up to 5 "ports" consisting
+of 8 channels each. It reads up to 32 1-bit channels but can only read
+and write a whole port at once - it needs to handle up to 5 ports as the
+first channel it reads might not be aligned on a port boundary. It
+breaks out of the loop early if the next port it handles is beyond the
+final port on the card. It also breaks out early on the 5th port in the
+loop if the first channel was aligned. Unfortunately, it doesn't check
+that the current port it is dealing with belongs to the comedi subdevice
+the `insn_bits` handler is acting on. That's a bug.
+
+Redo the `for` loop to terminate after the final port belonging to the
+subdevice, changing the loop variable in the process to simplify things
+a bit. The `for` loop could now try and handle more than 5 ports if the
+subdevice has more than 40 channels, but the test `if (bitshift >= 32)`
+ensures it will break out early after 4 or 5 ports (depending on whether
+the first channel is aligned on a port boundary). (`bitshift` will be
+between -7 and 7 inclusive on the first iteration, increasing by 8 for
+each subsequent operation.)
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/ni_65xx.c | 26 +++++++++++---------------
+ 1 file changed, 11 insertions(+), 15 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -411,29 +411,25 @@ static int ni_65xx_dio_insn_bits(struct
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+ {
+- unsigned base_bitfield_channel;
+- const unsigned max_ports_per_bitfield = 5;
++ int base_bitfield_channel;
+ unsigned read_bits = 0;
+- unsigned j;
++ int last_port_offset = ni_65xx_port_by_channel(s->n_chan - 1);
++ int port_offset;
++
+ if (insn->n != 2)
+ return -EINVAL;
+ base_bitfield_channel = CR_CHAN(insn->chanspec);
+- for (j = 0; j < max_ports_per_bitfield; ++j) {
+- const unsigned port_offset =
+- ni_65xx_port_by_channel(base_bitfield_channel) + j;
+- const unsigned port =
+- sprivate(s)->base_port + port_offset;
+- unsigned base_port_channel;
++ for (port_offset = ni_65xx_port_by_channel(base_bitfield_channel);
++ port_offset <= last_port_offset; port_offset++) {
++ unsigned port = sprivate(s)->base_port + port_offset;
++ int base_port_channel = port_offset * ni_65xx_channels_per_port;
+ unsigned port_mask, port_data, port_read_bits;
+- int bitshift;
+- if (port >= ni_65xx_total_num_ports(board(dev)))
++ int bitshift = base_port_channel - base_bitfield_channel;
++
++ if (bitshift >= 32)
+ break;
+- base_port_channel = port_offset * ni_65xx_channels_per_port;
+ port_mask = data[0];
+ port_data = data[1];
+- bitshift = base_port_channel - base_bitfield_channel;
+- if (bitshift >= 32 || bitshift <= -32)
+- break;
+ if (bitshift > 0) {
+ port_mask >>= bitshift;
+ port_data >>= bitshift;