From 52aa51ba44c7bf86fcd87425da2586d68b03afa8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 4 Mar 2010 16:00:54 -0800 Subject: [PATCH] some .27 patches --- ...-serial-transmitter-fully-empty-test.patch | 83 ++++++++++++ queue-2.6.27/series | 3 + ...s-only-copy-the-actual-data-received.patch | 50 ++++++++ ...n-up-the-as-structure-on-error-paths.patch | 121 ++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 queue-2.6.27/serial-8250-add-serial-transmitter-fully-empty-test.patch create mode 100644 queue-2.6.27/usb-usbfs-only-copy-the-actual-data-received.patch create mode 100644 queue-2.6.27/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch 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 index 00000000000..551c8fd6638 --- /dev/null +++ b/queue-2.6.27/serial-8250-add-serial-transmitter-fully-empty-test.patch @@ -0,0 +1,83 @@ +From bca476139d2ded86be146dae09b06e22548b67f3 Mon Sep 17 00:00:00 2001 +From: Dick Hollenbeck +Date: Wed, 9 Dec 2009 12:31:34 -0800 +Subject: serial: 8250: add serial transmitter fully empty test + +From: Dick Hollenbeck + +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 +Signed-off-by: Alan Cox +Cc: Kees Schoenmakers +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + */ diff --git a/queue-2.6.27/series b/queue-2.6.27/series index 72967312559..aaed9b5851c 100644 --- a/queue-2.6.27/series +++ b/queue-2.6.27/series @@ -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 index 00000000000..8565f4e22e5 --- /dev/null +++ b/queue-2.6.27/usb-usbfs-only-copy-the-actual-data-received.patch @@ -0,0 +1,50 @@ +From d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 Mon Sep 17 00:00:00 2001 +From: Greg KH +Date: Mon, 15 Feb 2010 09:37:46 -0800 +Subject: USB: usbfs: only copy the actual data received + +From: Greg KH + +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 +Tested-by: Marcus Meissner +Cc: Alan Stern +Cc: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a84197c2a36 --- /dev/null +++ b/queue-2.6.27/usb-usbfs-properly-clean-up-the-as-structure-on-error-paths.patch @@ -0,0 +1,121 @@ +From ddeee0b2eec2a51b0712b04de4b39e7bec892a53 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 16 Feb 2010 12:35:07 -0800 +Subject: USB: usbfs: properly clean up the as structure on error paths + +From: Linus Torvalds + +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 +Cc: Alan Stern +Cc: Marcus Meissner +Signed-off-by: Greg Kroah-Hartman + +--- + 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 -- 2.47.3