aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-11-29 12:04:15 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-29 12:04:15 -0800
commit731e918a4a85c611ca2b7bca552c5f4ae10d1f53 (patch)
treec39cb1442ef9a4c4f7ae8bc2459e6a7e01557343 /usb
parent5ee9d5564f1372dcf7cb6dcfa052bd7368657f40 (diff)
downloadpatches-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.patch34
-rw-r--r--usb/usb-input-touchkitusb-handle-multiple-packets.patch218
-rw-r--r--usb/usbserial-adds-missing-checks-and-bug-fix.patch130
-rw-r--r--usb/usbserial-race-condition-fix.patch126
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 00000000000000..23447650111754
--- /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 00000000000000..dadc0de366c31f
--- /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 00000000000000..e38f80a15b261f
--- /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 00000000000000..54ffc203291911
--- /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;