From: Greg Kroah-Hartman Date: Thu, 10 Oct 2013 22:55:39 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.0.100~6^2~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a73bad713d3991aaba0fcdd6ed1a649c6964a53b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch --- diff --git a/queue-3.0/series b/queue-3.0/series index fbf85964bde..59e670ee162 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 00000000000..a33b0d408e8 --- /dev/null +++ b/queue-3.0/staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch @@ -0,0 +1,82 @@ +From abbotti@mev.co.uk Thu Oct 10 15:53:41 2013 +From: Ian Abbott +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 +Message-ID: <1381398826-12693-1-git-send-email-abbotti@mev.co.uk> + +From: Ian Abbott + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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;