diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-29 12:04:15 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-29 12:04:15 -0800 |
commit | 731e918a4a85c611ca2b7bca552c5f4ae10d1f53 (patch) | |
tree | c39cb1442ef9a4c4f7ae8bc2459e6a7e01557343 /usb | |
parent | 5ee9d5564f1372dcf7cb6dcfa052bd7368657f40 (diff) | |
download | patches-731e918a4a85c611ca2b7bca552c5f4ae10d1f53.tar.gz |
2.6.15-rc3 refresh and usb, driver core, and i2c patches
Diffstat (limited to 'usb')
-rw-r--r-- | usb/usb-don-t-allocate-dma-pools-for-pio-hcds.patch | 34 | ||||
-rw-r--r-- | usb/usb-input-touchkitusb-handle-multiple-packets.patch | 218 | ||||
-rw-r--r-- | usb/usbserial-adds-missing-checks-and-bug-fix.patch | 130 | ||||
-rw-r--r-- | usb/usbserial-race-condition-fix.patch | 126 |
4 files changed, 508 insertions, 0 deletions
diff --git a/usb/usb-don-t-allocate-dma-pools-for-pio-hcds.patch b/usb/usb-don-t-allocate-dma-pools-for-pio-hcds.patch new file mode 100644 index 0000000000000..2344765011175 --- /dev/null +++ b/usb/usb-don-t-allocate-dma-pools-for-pio-hcds.patch @@ -0,0 +1,34 @@ +From david-b@pacbell.net Mon Nov 28 09:33:38 2005 +From: Chris Humbert <mahadri-kernel@drigon.com> +Subject: USB: don't allocate dma pools for PIO HCDs +Date: Mon, 28 Nov 2005 09:29:23 -0800 +Cc: David Brownell <david-b@pacbell.net> +Content-Disposition: inline +Message-Id: <200511280929.23666.david-b@pacbell.net> + +USB: don't allocate dma pools for PIO HCDs + +hcd_buffer_alloc() and hcd_buffer_free() have a similar dma_mask +check and revert to kmalloc()/kfree(), but hcd_buffer_create() +doesn't check dma_mask and allocates unused dma pools. + +Signed-off-by: Chris Humbert <mahadri-kernel@drigon.com> +Acked-by: David Brownell <david-b@pacbell.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/buffer.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/core/buffer.c ++++ gregkh-2.6/drivers/usb/core/buffer.c +@@ -55,6 +55,9 @@ int hcd_buffer_create (struct usb_hcd *h + char name [16]; + int i, size; + ++ if (!hcd->self.controller->dma_mask) ++ return 0; ++ + for (i = 0; i < HCD_BUFFER_POOLS; i++) { + if (!(size = pool_max [i])) + continue; diff --git a/usb/usb-input-touchkitusb-handle-multiple-packets.patch b/usb/usb-input-touchkitusb-handle-multiple-packets.patch new file mode 100644 index 0000000000000..dadc0de366c31 --- /dev/null +++ b/usb/usb-input-touchkitusb-handle-multiple-packets.patch @@ -0,0 +1,218 @@ +From daniel.ritz-ml@swissonline.ch Sun Nov 27 13:57:24 2005 +From: Daniel Ritz <daniel.ritz-ml@swissonline.ch> +To: Greg KH <gregkh@suse.de>, Vojtech Pavlik <vojtech@suse.cz> +Subject: usb/input/touchkitusb: handle multiple packets +Date: Sun, 27 Nov 2005 22:23:38 +0100 +Content-Disposition: inline +Message-Id: <200511272223.38923.daniel.ritz-ml@swissonline.ch> + +Some versions of the controller seem to put multiple report packet into a +single urb. also it can happen that a packet is split across multiple urbs. +unpatched you get a jumpy cursor on some screens. +the patch does: +- handle multiple packets per urb +- handle packets split across multiple urb +- check packet type +- cleanups + +Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c +index 7420c6b..e62586e 100644 +--- + drivers/usb/input/touchkitusb.c | 148 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 126 insertions(+), 22 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/input/touchkitusb.c ++++ gregkh-2.6/drivers/usb/input/touchkitusb.c +@@ -1,7 +1,7 @@ + /****************************************************************************** + * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens + * +- * Copyright (C) 2004 by Daniel Ritz ++ * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch> + * Copyright (C) by Todd E. Johnson (mtouchusb.c) + * + * This program is free software; you can redistribute it and/or +@@ -41,15 +41,13 @@ + #define TOUCHKIT_MAX_YC 0x07ff + #define TOUCHKIT_YC_FUZZ 0x0 + #define TOUCHKIT_YC_FLAT 0x0 +-#define TOUCHKIT_REPORT_DATA_SIZE 8 ++#define TOUCHKIT_REPORT_DATA_SIZE 16 + + #define TOUCHKIT_DOWN 0x01 +-#define TOUCHKIT_POINT_TOUCH 0x81 +-#define TOUCHKIT_POINT_NOTOUCH 0x80 + +-#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0) +-#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4]) +-#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2]) ++#define TOUCHKIT_PKT_TYPE_MASK 0xFE ++#define TOUCHKIT_PKT_TYPE_REPT 0x80 ++#define TOUCHKIT_PKT_TYPE_DIAG 0x0A + + #define DRIVER_VERSION "v0.1" + #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" +@@ -62,6 +60,8 @@ MODULE_PARM_DESC(swap_xy, "If set X and + struct touchkit_usb { + unsigned char *data; + dma_addr_t data_dma; ++ char buffer[TOUCHKIT_REPORT_DATA_SIZE]; ++ int buf_len; + struct urb *irq; + struct usb_device *udev; + struct input_dev *input; +@@ -77,11 +77,128 @@ static struct usb_device_id touchkit_dev + {} + }; + ++/* helpers to read the data */ ++static inline int touchkit_get_touched(char *data) ++{ ++ return (data[0] & TOUCHKIT_DOWN) ? 1 : 0; ++} ++ ++static inline int touchkit_get_x(char *data) ++{ ++ return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F); ++} ++ ++static inline int touchkit_get_y(char *data) ++{ ++ return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F); ++} ++ ++ ++/* processes one input packet. */ ++static void touchkit_process_pkt(struct touchkit_usb *touchkit, ++ struct pt_regs *regs, char *pkt) ++{ ++ int x, y; ++ ++ /* only process report packets */ ++ if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT) ++ return; ++ ++ if (swap_xy) { ++ y = touchkit_get_x(pkt); ++ x = touchkit_get_y(pkt); ++ } else { ++ x = touchkit_get_x(pkt); ++ y = touchkit_get_y(pkt); ++ } ++ ++ input_regs(touchkit->input, regs); ++ input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt)); ++ input_report_abs(touchkit->input, ABS_X, x); ++ input_report_abs(touchkit->input, ABS_Y, y); ++ input_sync(touchkit->input); ++} ++ ++ ++static int touchkit_get_pkt_len(char *buf) ++{ ++ switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) { ++ case TOUCHKIT_PKT_TYPE_REPT: ++ return 5; ++ ++ case TOUCHKIT_PKT_TYPE_DIAG: ++ return buf[1] + 2; ++ } ++ ++ return 0; ++} ++ ++static void touchkit_process(struct touchkit_usb *touchkit, int len, ++ struct pt_regs *regs) ++{ ++ char *buffer; ++ int pkt_len, buf_len, pos; ++ ++ /* if the buffer contains data, append */ ++ if (unlikely(touchkit->buf_len)) { ++ int tmp; ++ ++ /* if only 1 byte in buffer, add another one to get length */ ++ if (touchkit->buf_len == 1) ++ touchkit->buffer[1] = touchkit->data[0]; ++ ++ pkt_len = touchkit_get_pkt_len(touchkit->buffer); ++ ++ /* unknown packet: drop everything */ ++ if (!pkt_len) ++ return; ++ ++ /* append, process */ ++ tmp = pkt_len - touchkit->buf_len; ++ memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp); ++ touchkit_process_pkt(touchkit, regs, touchkit->buffer); ++ ++ buffer = touchkit->data + tmp; ++ buf_len = len - tmp; ++ } else { ++ buffer = touchkit->data; ++ buf_len = len; ++ } ++ ++ /* only one byte left in buffer */ ++ if (unlikely(buf_len == 1)) { ++ touchkit->buffer[0] = buffer[0]; ++ touchkit->buf_len = 1; ++ return; ++ } ++ ++ /* loop over the buffer */ ++ pos = 0; ++ while (pos < buf_len) { ++ /* get packet len */ ++ pkt_len = touchkit_get_pkt_len(buffer + pos); ++ ++ /* unknown packet: drop everything */ ++ if (unlikely(!pkt_len)) ++ return; ++ ++ /* full packet: process */ ++ if (likely(pkt_len <= buf_len)) { ++ touchkit_process_pkt(touchkit, regs, buffer + pos); ++ } else { ++ /* incomplete packet: save in buffer */ ++ memcpy(touchkit->buffer, buffer + pos, buf_len - pos); ++ touchkit->buf_len = buf_len - pos; ++ } ++ pos += pkt_len; ++ } ++} ++ ++ + static void touchkit_irq(struct urb *urb, struct pt_regs *regs) + { + struct touchkit_usb *touchkit = urb->context; + int retval; +- int x, y; + + switch (urb->status) { + case 0: +@@ -105,20 +222,7 @@ static void touchkit_irq(struct urb *urb + goto exit; + } + +- if (swap_xy) { +- y = TOUCHKIT_GET_X(touchkit->data); +- x = TOUCHKIT_GET_Y(touchkit->data); +- } else { +- x = TOUCHKIT_GET_X(touchkit->data); +- y = TOUCHKIT_GET_Y(touchkit->data); +- } +- +- input_regs(touchkit->input, regs); +- input_report_key(touchkit->input, BTN_TOUCH, +- TOUCHKIT_GET_TOUCHED(touchkit->data)); +- input_report_abs(touchkit->input, ABS_X, x); +- input_report_abs(touchkit->input, ABS_Y, y); +- input_sync(touchkit->input); ++ touchkit_process(touchkit, urb->actual_length, regs); + + exit: + retval = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/usb/usbserial-adds-missing-checks-and-bug-fix.patch b/usb/usbserial-adds-missing-checks-and-bug-fix.patch new file mode 100644 index 0000000000000..e38f80a15b261 --- /dev/null +++ b/usb/usbserial-adds-missing-checks-and-bug-fix.patch @@ -0,0 +1,130 @@ +From lcapitulino@mandriva.com.br Mon Nov 28 13:24:54 2005 +Date: Mon, 28 Nov 2005 19:16:05 -0200 +From: Luiz Fernando Capitulino <lcapitulino@mandriva.com.br> +To: gregkh@suse.de +Cc: akpm <akpm@osdl.org>, <ehabkost@mandriva.com> +Subject: usbserial: Adds missing checks and bug fix. +Message-Id: <20051128191605.096bb777.lcapitulino@mandriva.com.br> + + +Checks if 'port' is NULL before using it in all tty operations, this +can avoid NULL pointer dereferences. + +Signed-off-by: Luiz Capitulino <lcapitulino@mandriva.com.br> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/usb-serial.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c ++++ gregkh-2.6/drivers/usb/serial/usb-serial.c +@@ -188,6 +188,8 @@ static int serial_open (struct tty_struc + + portNumber = tty->index - serial->minor; + port = serial->port[portNumber]; ++ if (!port) ++ return -ENODEV; + + ++port->open_count; + +@@ -258,6 +260,9 @@ static int serial_write (struct tty_stru + struct usb_serial_port *port = tty->driver_data; + int retval = -EINVAL; + ++ if (!port) ++ goto exit; ++ + dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); + + if (!port->open_count) { +@@ -277,6 +282,9 @@ static int serial_write_room (struct tty + struct usb_serial_port *port = tty->driver_data; + int retval = -EINVAL; + ++ if (!port) ++ goto exit; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -296,6 +304,9 @@ static int serial_chars_in_buffer (struc + struct usb_serial_port *port = tty->driver_data; + int retval = -EINVAL; + ++ if (!port) ++ goto exit; ++ + dbg("%s = port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -314,6 +325,9 @@ static void serial_throttle (struct tty_ + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ return; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -330,6 +344,9 @@ static void serial_unthrottle (struct tt + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ return; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -347,6 +364,9 @@ static int serial_ioctl (struct tty_stru + struct usb_serial_port *port = tty->driver_data; + int retval = -ENODEV; + ++ if (!port) ++ goto exit; ++ + dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); + + if (!port->open_count) { +@@ -368,6 +388,9 @@ static void serial_set_termios (struct t + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ return; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -384,6 +407,9 @@ static void serial_break (struct tty_str + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ return; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -445,6 +471,9 @@ static int serial_tiocmget (struct tty_s + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ goto exit; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { +@@ -464,6 +493,9 @@ static int serial_tiocmset (struct tty_s + { + struct usb_serial_port *port = tty->driver_data; + ++ if (!port) ++ goto exit; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!port->open_count) { diff --git a/usb/usbserial-race-condition-fix.patch b/usb/usbserial-race-condition-fix.patch new file mode 100644 index 0000000000000..54ffc20329191 --- /dev/null +++ b/usb/usbserial-race-condition-fix.patch @@ -0,0 +1,126 @@ +From lcapitulino@mandriva.com.br Mon Nov 28 13:24:54 2005 +Date: Mon, 28 Nov 2005 19:16:07 -0200 +From: Luiz Fernando Capitulino <lcapitulino@mandriva.com.br> +To: gregkh@suse.de +Cc: akpm <akpm@osdl.org>, <ehabkost@mandriva.com> +Subject: usbserial: race-condition fix. +Message-Id: <20051128191607.595f1725.lcapitulino@mandriva.com.br> + + +There is a race-condition in usb-serial driver that can be triggered if +a processes does 'port->tty->driver_data = NULL' in serial_close() while +other processes is in kernel-space about to call serial_ioctl() on the +same port. + +This happens because a process can open the device while there is +another one closing it. + +The patch below fixes that by adding a semaphore to ensure that no +process will open the device while another process is closing it. + +Note that we can't use spinlocks here, since serial_open() and +serial_close() can sleep. + + +Signed-off-by: Luiz Capitulino <lcapitulino@mandriva.com.br> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/usb-serial.c | 14 +++++++++++++- + drivers/usb/serial/usb-serial.h | 4 ++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c ++++ gregkh-2.6/drivers/usb/serial/usb-serial.c +@@ -30,6 +30,7 @@ + #include <linux/list.h> + #include <linux/smp_lock.h> + #include <asm/uaccess.h> ++#include <asm/semaphore.h> + #include <linux/usb.h> + #include "usb-serial.h" + #include "pl2303.h" +@@ -190,6 +191,9 @@ static int serial_open (struct tty_struc + port = serial->port[portNumber]; + if (!port) + return -ENODEV; ++ ++ if (down_interruptible(&port->sem)) ++ return -ERESTARTSYS; + + ++port->open_count; + +@@ -215,6 +219,7 @@ static int serial_open (struct tty_struc + goto bailout_module_put; + } + ++ up(&port->sem); + return 0; + + bailout_module_put: +@@ -222,6 +227,7 @@ bailout_module_put: + bailout_kref_put: + kref_put(&serial->kref, destroy_serial); + port->open_count = 0; ++ up(&port->sem); + return retval; + } + +@@ -234,8 +240,10 @@ static void serial_close(struct tty_stru + + dbg("%s - port %d", __FUNCTION__, port->number); + ++ down(&port->sem); ++ + if (port->open_count == 0) +- return; ++ goto out; + + --port->open_count; + if (port->open_count == 0) { +@@ -253,6 +261,9 @@ static void serial_close(struct tty_stru + } + + kref_put(&port->serial->kref, destroy_serial); ++ ++out: ++ up(&port->sem); + } + + static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) +@@ -774,6 +785,7 @@ int usb_serial_probe(struct usb_interfac + port->number = i + serial->minor; + port->serial = serial; + spin_lock_init(&port->lock); ++ sema_init(&port->sem, 1); + INIT_WORK(&port->work, usb_serial_port_softint, port); + serial->port[i] = port; + } +--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.h ++++ gregkh-2.6/drivers/usb/serial/usb-serial.h +@@ -16,6 +16,7 @@ + + #include <linux/config.h> + #include <linux/kref.h> ++#include <asm/semaphore.h> + + #define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ + #define SERIAL_TTY_MINORS 255 /* loads of devices :) */ +@@ -30,6 +31,8 @@ + * @serial: pointer back to the struct usb_serial owner of this port. + * @tty: pointer to the corresponding tty for this port. + * @lock: spinlock to grab when updating portions of this structure. ++ * @sem: semaphore used to synchronize serial_open() and serial_close() ++ * access for this port. + * @number: the number of the port (the minor number). + * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. + * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. +@@ -60,6 +63,7 @@ struct usb_serial_port { + struct usb_serial * serial; + struct tty_struct * tty; + spinlock_t lock; ++ struct semaphore sem; + unsigned char number; + + unsigned char * interrupt_in_buffer; |