]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
some .27 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Fri, 5 Mar 2010 00:00:54 +0000 (16:00 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 5 Mar 2010 00:00:54 +0000 (16:00 -0800)
queue-2.6.27/serial-8250-add-serial-transmitter-fully-empty-test.patch [new file with mode: 0644]
queue-2.6.27/series
queue-2.6.27/usb-usbfs-only-copy-the-actual-data-received.patch [new file with mode: 0644]
queue-2.6.27/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch [new file with mode: 0644]

diff --git a/queue-2.6.27/serial-8250-add-serial-transmitter-fully-empty-test.patch b/queue-2.6.27/serial-8250-add-serial-transmitter-fully-empty-test.patch
new file mode 100644 (file)
index 0000000..551c8fd
--- /dev/null
@@ -0,0 +1,83 @@
+From bca476139d2ded86be146dae09b06e22548b67f3 Mon Sep 17 00:00:00 2001
+From: Dick Hollenbeck <dick@softplc.com>
+Date: Wed, 9 Dec 2009 12:31:34 -0800
+Subject: serial: 8250: add serial transmitter fully empty test
+
+From: Dick Hollenbeck <dick@softplc.com>
+
+commit bca476139d2ded86be146dae09b06e22548b67f3 upstream.
+
+When controlling an industrial radio modem it can be necessary to
+manipulate the handshake lines in order to control the radio modem's
+transmitter, from userspace.
+
+The transmitter should not be turned off before all characters have been
+transmitted.  serial8250_tx_empty() was reporting that all characters were
+transmitted before they actually were.
+
+===
+
+Discovered in parallel with more testing and analysis by Kees Schoenmakers
+as follows:
+
+I ran into an NetMos 9835 serial pci board which behaves a little
+different than the standard.  This type of expansion board is very common.
+
+"Standard" 8250 compatible devices clear the 'UART_LST_TEMT" bit together
+with the "UART_LSR_THRE" bit when writing data to the device.
+
+The NetMos device does it slightly different
+
+I believe that the TEMT bit is coupled to the shift register.  The problem
+is that after writing data to the device and very quickly after that one
+does call serial8250_tx_empty, it returns the wrong information.
+
+My patch makes the test more robust (and solves the problem) and it does
+not affect the already correct devices.
+
+Alan:
+
+  We may yet need to quirk this but now we know which chips we have a
+  way to do that should we find this breaks some other 8250 clone with
+  dodgy THRE.
+
+Signed-off-by: Dick Hollenbeck <dick@softplc.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Kees Schoenmakers <k.schoenmakers@sigmae.nl>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -70,6 +70,9 @@ static unsigned int nr_uarts = CONFIG_SE
+ #define PASS_LIMIT    256
++#define BOTH_EMPTY    (UART_LSR_TEMT | UART_LSR_THRE)
++
++
+ /*
+  * We default to IRQ0 for the "no irq" hack.   Some
+  * machine types want others as well - they're free
+@@ -1656,7 +1659,7 @@ static unsigned int serial8250_tx_empty(
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+-      return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
++      return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+ }
+ static unsigned int serial8250_get_mctrl(struct uart_port *port)
+@@ -1714,8 +1717,6 @@ static void serial8250_break_ctl(struct
+       spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+-
+ /*
+  *    Wait for transmitter & holding register to empty
+  */
index 7296731255963835346681f77b304cf4b7df6571..aaed9b5851c198d2853d6e55af1f454e53b90e07 100644 (file)
@@ -19,3 +19,6 @@ sched-fine-tune-sd_sibling_init.patch
 sched-wakeup-preempt-when-small-overlap.patch
 drivers-char-mem.c-avoid-oom-lockup-during-large-reads-from-dev-zero.patch
 i2c-do-not-use-device-name-after-device_unregister.patch
+serial-8250-add-serial-transmitter-fully-empty-test.patch
+usb-usbfs-only-copy-the-actual-data-received.patch
+usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
diff --git a/queue-2.6.27/usb-usbfs-only-copy-the-actual-data-received.patch b/queue-2.6.27/usb-usbfs-only-copy-the-actual-data-received.patch
new file mode 100644 (file)
index 0000000..8565f4e
--- /dev/null
@@ -0,0 +1,50 @@
+From d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 Mon Sep 17 00:00:00 2001
+From: Greg KH <greg@kroah.com>
+Date: Mon, 15 Feb 2010 09:37:46 -0800
+Subject: USB: usbfs: only copy the actual data received
+
+From: Greg KH <greg@kroah.com>
+
+commit d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 upstream.
+
+We need to only copy the data received by the device to userspace, not
+the whole kernel buffer, which can contain "stale" data.
+
+Thanks to Marcus Meissner for pointing this out and testing the fix.
+
+Reported-by: Marcus Meissner <meissner@suse.de>
+Tested-by: Marcus Meissner <meissner@suse.de>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devio.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1224,9 +1224,9 @@ static int processcompl(struct async *as
+       void __user *addr = as->userurb;
+       unsigned int i;
+-      if (as->userbuffer)
++      if (as->userbuffer && urb->actual_length)
+               if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+-                               urb->transfer_buffer_length))
++                               urb->actual_length))
+                       goto err_out;
+       if (put_user(as->status, &userurb->status))
+               goto err_out;
+@@ -1347,9 +1347,9 @@ static int processcompl_compat(struct as
+       void __user *addr = as->userurb;
+       unsigned int i;
+-      if (as->userbuffer)
++      if (as->userbuffer && urb->actual_length)
+               if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+-                               urb->transfer_buffer_length))
++                               urb->actual_length))
+                       return -EFAULT;
+       if (put_user(as->status, &userurb->status))
+               return -EFAULT;
diff --git a/queue-2.6.27/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch b/queue-2.6.27/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch
new file mode 100644 (file)
index 0000000..a84197c
--- /dev/null
@@ -0,0 +1,121 @@
+From ddeee0b2eec2a51b0712b04de4b39e7bec892a53 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 16 Feb 2010 12:35:07 -0800
+Subject: USB: usbfs: properly clean up the as structure on error paths
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit ddeee0b2eec2a51b0712b04de4b39e7bec892a53 upstream.
+
+I notice that the processcompl_compat() function seems to be leaking the
+'struct async *as' in the error paths.
+
+I think that the calling convention is fundamentally buggered. The
+caller is the one that did the "reap_as()" to get the as thing, the
+caller should be the one to free it too.
+
+Freeing it in the caller also means that it very clearly always gets
+freed, and avoids the need for any "free in the error case too".
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Marcus Meissner <meissner@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devio.c |   40 ++++++++++++++++++++++++++--------------
+ 1 file changed, 26 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1246,14 +1246,11 @@ static int processcompl(struct async *as
+               }
+       }
+-      free_async(as);
+-
+       if (put_user(addr, (void __user * __user *)arg))
+               return -EFAULT;
+       return 0;
+ err_out:
+-      free_async(as);
+       return -EFAULT;
+ }
+@@ -1283,8 +1280,11 @@ static struct async *reap_as(struct dev_
+ static int proc_reapurb(struct dev_state *ps, void __user *arg)
+ {
+       struct async *as = reap_as(ps);
+-      if (as)
+-              return processcompl(as, (void __user * __user *)arg);
++      if (as) {
++              int retval = processcompl(as, (void __user * __user *)arg);
++              free_async(as);
++              return retval;
++      }
+       if (signal_pending(current))
+               return -EINTR;
+       return -EIO;
+@@ -1292,11 +1292,16 @@ static int proc_reapurb(struct dev_state
+ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
+ {
++      int retval;
+       struct async *as;
+-      if (!(as = async_getcompleted(ps)))
+-              return -EAGAIN;
+-      return processcompl(as, (void __user * __user *)arg);
++      as = async_getcompleted(ps);
++      retval = -EAGAIN;
++      if (as) {
++              retval = processcompl(as, (void __user * __user *)arg);
++              free_async(as);
++      }
++      return retval;
+ }
+ #ifdef CONFIG_COMPAT
+@@ -1369,7 +1374,6 @@ static int processcompl_compat(struct as
+               }
+       }
+-      free_async(as);
+       if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
+               return -EFAULT;
+       return 0;
+@@ -1378,8 +1382,11 @@ static int processcompl_compat(struct as
+ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
+ {
+       struct async *as = reap_as(ps);
+-      if (as)
+-              return processcompl_compat(as, (void __user * __user *)arg);
++      if (as) {
++              int retval = processcompl_compat(as, (void __user * __user *)arg);
++              free_async(as);
++              return retval;
++      }
+       if (signal_pending(current))
+               return -EINTR;
+       return -EIO;
+@@ -1387,11 +1394,16 @@ static int proc_reapurb_compat(struct de
+ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
+ {
++      int retval;
+       struct async *as;
+-      if (!(as = async_getcompleted(ps)))
+-              return -EAGAIN;
+-      return processcompl_compat(as, (void __user * __user *)arg);
++      retval = -EAGAIN;
++      as = async_getcompleted(ps);
++      if (as) {
++              retval = processcompl_compat(as, (void __user * __user *)arg);
++              free_async(as);
++      }
++      return retval;
+ }
+ #endif