]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2013 22:55:39 +0000 (15:55 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2013 22:55:39 +0000 (15:55 -0700)
added patches:
staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch

queue-3.0/series
queue-3.0/staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch [new file with mode: 0644]

index fbf85964bded1e1cd3fd6ce8a703d97c5e7e1a2f..59e670ee1627e041301fe7f1c92922de66fbba57 100644 (file)
@@ -28,3 +28,4 @@ sparc64-fix-not-sra-ed-o5-in-32-bit-traced-syscall.patch
 sparc32-fix-exit-flag-passed-from-traced-sys_sigreturn.patch
 kernel-kmod.c-check-for-null-in-call_usermodehelper_exec.patch
 usb-serial-option-ignore-card-reader-interface-on-huawei-e1750.patch
+staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch
diff --git a/queue-3.0/staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch b/queue-3.0/staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch
new file mode 100644 (file)
index 0000000..a33b0d4
--- /dev/null
@@ -0,0 +1,82 @@
+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;