aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-05-04 16:43:43 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2006-05-04 16:43:43 -0700
commiteedb5a80e5779bb431e036a85ce268d2f9898e04 (patch)
tree3ecd64b67bbf50b5841229a21aeed38c52751c9a /usb
parentc254ef31aea65814b54e8eed48108856450ebe04 (diff)
downloadpatches-eedb5a80e5779bb431e036a85ce268d2f9898e04.tar.gz
usb and pci patches added
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-ftdi_sio-add-device-id-for-act-solutions-homepro-zwave-interface.patch39
-rw-r--r--usb/usb-ftdi_sio-add-support-for-hcg-hf-dual-iso-rfid-reader.patch45
-rw-r--r--usb/usb-phidget-interfacekit-make-inputs-pollable-and-new-device-support.patch612
-rw-r--r--usb/usb-shuttle_usbat-fix-handling-of-scatter-gather-buffers.patch221
-rw-r--r--usb/usb-shuttle_usbat-hardcode-detection-of-hp-cdrw-devices.patch170
-rw-r--r--usb/usb-ub-oops-in-block_uevent.patch72
-rw-r--r--usb/usb-usbcore-don-t-check-the-device-s-power-source.patch68
7 files changed, 1227 insertions, 0 deletions
diff --git a/usb/usb-ftdi_sio-add-device-id-for-act-solutions-homepro-zwave-interface.patch b/usb/usb-ftdi_sio-add-device-id-for-act-solutions-homepro-zwave-interface.patch
new file mode 100644
index 00000000000000..150cfc178758e6
--- /dev/null
+++ b/usb/usb-ftdi_sio-add-device-id-for-act-solutions-homepro-zwave-interface.patch
@@ -0,0 +1,39 @@
+From razvan.g@plutohome.com Thu May 4 01:35:37 2006
+Message-ID: <4459BCE5.7050502@plutohome.com>
+Date: Thu, 04 May 2006 11:35:49 +0300
+From: Razvan Gavril <razvan.g@plutohome.com>
+To: Greg KH <greg@kroah.com>
+CC: linux-kernel@vger.kernel.org
+Subject: USB: ftdi_sio: add device id for ACT Solutions HomePro ZWave interface
+
+Signed-off-by: Razvan Gavril <razvan.g@plutohome.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio.h | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c
++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c
+@@ -307,6 +307,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIR
+
+
+ static struct usb_device_id id_table_combined [] = {
++ { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
+--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.h
++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.h
+@@ -32,6 +32,10 @@
+ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */
+
+
++/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
++#define FTDI_ACTZWAVE_PID 0xF2D0
++
++
+ /* www.irtrans.de device */
+ #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
+
diff --git a/usb/usb-ftdi_sio-add-support-for-hcg-hf-dual-iso-rfid-reader.patch b/usb/usb-ftdi_sio-add-support-for-hcg-hf-dual-iso-rfid-reader.patch
new file mode 100644
index 00000000000000..1e915982090bcc
--- /dev/null
+++ b/usb/usb-ftdi_sio-add-support-for-hcg-hf-dual-iso-rfid-reader.patch
@@ -0,0 +1,45 @@
+From ian.abbott@mev.co.uk Thu May 4 03:34:52 2006
+Message-ID: <4459D8B1.9010803@mev.co.uk>
+Date: Thu, 04 May 2006 11:34:25 +0100
+From: Ian Abbott <abbotti@mev.co.uk>
+Cc: Greg KH <greg@kroah.com>, ftdi-usb-sio-devel@lists.sourceforge.net, antonios <anton@goto10.org>
+Subject: USB: ftdi_sio: Add support for HCG HF Dual ISO RFID Reader
+
+This patch adds support for ACG Identification Technologies GmbH's HF
+Dual ISO Reader (an RFID tag reader) to the ftdi_sio driver's device ID
+table. The product ID was supplied by anotonios (anton at goto10 dot
+org) on the ftdi-usb-sio-devel list and subsequently verified by myself
+(Ian Abbott).
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio.h | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c
++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c
+@@ -498,6 +498,7 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
+ { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+ { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
+ { }, /* Optional parameter entry */
+ { } /* Terminating entry */
+ };
+--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.h
++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.h
+@@ -426,6 +426,11 @@
+ #define PAPOUCH_VID 0x5050 /* Vendor ID */
+ #define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */
+
++/*
++ * ACG Identification Technologies GmbH products (http://www.acg.de/).
++ * Submitted by anton -at- goto10 -dot- org.
++ */
++#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */
+
+ /* Commands */
+ #define FTDI_SIO_RESET 0 /* Reset the port */
diff --git a/usb/usb-phidget-interfacekit-make-inputs-pollable-and-new-device-support.patch b/usb/usb-phidget-interfacekit-make-inputs-pollable-and-new-device-support.patch
new file mode 100644
index 00000000000000..f9b60a324ad203
--- /dev/null
+++ b/usb/usb-phidget-interfacekit-make-inputs-pollable-and-new-device-support.patch
@@ -0,0 +1,612 @@
+From sean@mess.org Tue May 2 04:44:59 2006
+Date: Tue, 2 May 2006 11:44:43 +0000
+From: Sean Young <sean@mess.org>
+To: Greg KH <gregkh@suse.de>, Daniel Saakes <daniel.saakes@gmail.com>
+Cc: linux-usb-devel@lists.sourceforge.net
+Subject: USB Phidget InterfaceKit: make inputs pollable and new device support
+Message-ID: <20060502114443.GA57647@atlantis.8hz.com>
+Content-Disposition: inline
+
+Make inputs pollable using sysfs_notify and add support for the Phidget
+InterfaceKit 0/16/16. Various cleanups.
+
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Daniel Saakes <daniel@saakes.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/misc/phidgetkit.c | 305 ++++++++++++++++++++++++++++++------------
+ 1 file changed, 219 insertions(+), 86 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/misc/phidgetkit.c
++++ gregkh-2.6/drivers/usb/misc/phidgetkit.c
+@@ -1,7 +1,8 @@
+ /*
+ * USB PhidgetInterfaceKit driver 1.0
+ *
+- * Copyright (C) 2004 Sean Young <sean@mess.org>
++ * Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
++ * Copyright (C) 2005 Daniel Saakes <daniel@saakes.net>
+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -25,6 +26,7 @@
+
+ #define USB_VENDOR_ID_GLAB 0x06c2
+ #define USB_DEVICE_ID_INTERFACEKIT004 0x0040
++#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044
+ #define USB_DEVICE_ID_INTERFACEKIT888 0x0045
+ #define USB_DEVICE_ID_INTERFACEKIT047 0x0051
+ #define USB_DEVICE_ID_INTERFACEKIT088 0x0053
+@@ -32,7 +34,9 @@
+ #define USB_VENDOR_ID_WISEGROUP 0x0925
+ #define USB_DEVICE_ID_INTERFACEKIT884 0x8201
+
+-#define MAX_INTERFACES 8
++#define MAX_INTERFACES 16
++
++#define URB_INT_SIZE 8
+
+ struct driver_interfacekit {
+ int sensors;
+@@ -52,19 +56,24 @@ ifkit(8, 8, 8, 0);
+ ifkit(0, 4, 7, 1);
+ ifkit(8, 8, 4, 0);
+ ifkit(0, 8, 8, 1);
++ifkit(0, 16, 16, 0);
+
+-struct phidget_interfacekit {
++struct interfacekit {
+ struct usb_device *udev;
+ struct usb_interface *intf;
+ struct driver_interfacekit *ifkit;
+- int outputs[MAX_INTERFACES];
+- int inputs[MAX_INTERFACES];
+- int sensors[MAX_INTERFACES];
++ unsigned long outputs;
++ u8 inputs[MAX_INTERFACES];
++ u16 sensors[MAX_INTERFACES];
+ u8 lcd_files_on;
+
+ struct urb *irq;
+ unsigned char *data;
+ dma_addr_t data_dma;
++
++ struct work_struct do_notify;
++ unsigned long input_events;
++ unsigned long sensor_events;
+ };
+
+ static struct usb_device_id id_table[] = {
+@@ -76,33 +85,33 @@ static struct usb_device_id id_table[] =
+ .driver_info = (kernel_ulong_t)&ph_047},
+ {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
+ .driver_info = (kernel_ulong_t)&ph_088},
++ {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616),
++ .driver_info = (kernel_ulong_t)&ph_01616},
+ {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
+ .driver_info = (kernel_ulong_t)&ph_884},
+ {}
+ };
+ MODULE_DEVICE_TABLE(usb, id_table);
+
+-static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable)
++static int change_outputs(struct interfacekit *kit, int output_num, int enable)
+ {
+- unsigned char *buffer;
++ u8 *buffer;
+ int retval;
+- int n;
+
++ if (enable)
++ set_bit(output_num, &kit->outputs);
++ else
++ clear_bit(output_num, &kit->outputs);
++
+ buffer = kzalloc(4, GFP_KERNEL);
+ if (!buffer) {
+- dev_err(&kit->udev->dev, "%s - out of memory\n",
+- __FUNCTION__);
++ dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
++ buffer[0] = (u8)kit->outputs;
++ buffer[1] = (u8)(kit->outputs >> 8);
+
+- kit->outputs[output_num] = enable;
+- for (n=0; n<8; n++) {
+- if (kit->outputs[n]) {
+- buffer[0] |= 1 << n;
+- }
+- }
+-
+- dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]);
++ dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", kit->outputs);
+
+ retval = usb_control_msg(kit->udev,
+ usb_sndctrlpipe(kit->udev, 0),
+@@ -116,10 +125,10 @@ static int change_outputs(struct phidget
+ return retval < 0 ? retval : 0;
+ }
+
+-static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row)
++static int change_string(struct interfacekit *kit, const char *display, unsigned char row)
+ {
+ unsigned char *buffer;
+- unsigned char *form_buffer;
++ unsigned char *form_buffer;
+ int retval = -ENOMEM;
+ int i,j, len, buf_ptr;
+
+@@ -175,7 +184,7 @@ exit:
+ static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+ { \
+ struct usb_interface *intf = to_usb_interface(dev); \
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
++ struct interfacekit *kit = usb_get_intfdata(intf); \
+ change_string(kit, buf, number - 1); \
+ return count; \
+ } \
+@@ -186,7 +195,7 @@ set_lcd_line(2);
+ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {
+ struct usb_interface *intf = to_usb_interface(dev);
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf);
++ struct interfacekit *kit = usb_get_intfdata(intf);
+ int enabled;
+ unsigned char *buffer;
+ int retval = -ENOMEM;
+@@ -220,7 +229,7 @@ exit:
+ }
+ static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
+
+-static void remove_lcd_files(struct phidget_interfacekit *kit)
++static void remove_lcd_files(struct interfacekit *kit)
+ {
+ if (kit->lcd_files_on) {
+ dev_dbg(&kit->udev->dev, "Removing lcd files\n");
+@@ -233,7 +242,7 @@ static void remove_lcd_files(struct phid
+ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {
+ struct usb_interface *intf = to_usb_interface(dev);
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf);
++ struct interfacekit *kit = usb_get_intfdata(intf);
+ int enable;
+
+ if (kit->ifkit->has_lcd == 0)
+@@ -263,10 +272,10 @@ static DEVICE_ATTR(lcd, S_IWUGO, NULL, e
+
+ static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
+ {
+- struct phidget_interfacekit *kit = urb->context;
++ struct interfacekit *kit = urb->context;
+ unsigned char *buffer = kit->data;
++ int i, level, sensor;
+ int status;
+- int n;
+
+ switch (urb->status) {
+ case 0: /* success */
+@@ -280,22 +289,63 @@ static void interfacekit_irq(struct urb
+ goto resubmit;
+ }
+
+- for (n=0; n<8; n++) {
+- kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0;
++ /* digital inputs */
++ if (kit->ifkit->inputs == 16) {
++ for (i=0; i < 8; i++) {
++ level = (buffer[0] >> i) & 1;
++ if (kit->inputs[i] != level) {
++ kit->inputs[i] = level;
++ set_bit(i, &kit->input_events);
++ }
++ level = (buffer[1] >> i) & 1;
++ if (kit->inputs[8 + i] != level) {
++ kit->inputs[8 + i] = level;
++ set_bit(8 + i, &kit->input_events);
++ }
++ }
++ }
++ else if (kit->ifkit->inputs == 8) {
++ for (i=0; i < 8; i++) {
++ level = (buffer[1] >> i) & 1;
++ if (kit->inputs[i] != level) {
++ kit->inputs[i] = level;
++ set_bit(i, &kit->input_events);
++ }
++ }
+ }
+
+- if (buffer[0] & 1) {
+- kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256;
+- kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16;
+- kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256;
+- kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16;
+- } else {
+- kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256;
+- kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16;
+- kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256;
+- kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16;
++ /* analog inputs */
++ if (kit->ifkit->sensors) {
++ sensor = (buffer[0] & 1) ? 4 : 0;
++
++ level = buffer[2] + (buffer[3] & 0x0f) * 256;
++ if (level != kit->sensors[sensor]) {
++ kit->sensors[sensor] = level;
++ set_bit(sensor, &kit->sensor_events);
++ }
++ sensor++;
++ level = buffer[4] + (buffer[3] & 0xf0) * 16;
++ if (level != kit->sensors[sensor]) {
++ kit->sensors[sensor] = level;
++ set_bit(sensor, &kit->sensor_events);
++ }
++ sensor++;
++ level = buffer[5] + (buffer[6] & 0x0f) * 256;
++ if (level != kit->sensors[sensor]) {
++ kit->sensors[sensor] = level;
++ set_bit(sensor, &kit->sensor_events);
++ }
++ sensor++;
++ level = buffer[7] + (buffer[6] & 0xf0) * 16;
++ if (level != kit->sensors[sensor]) {
++ kit->sensors[sensor] = level;
++ set_bit(sensor, &kit->sensor_events);
++ }
+ }
+
++ if (kit->input_events || kit->sensor_events)
++ schedule_work(&kit->do_notify);
++
+ resubmit:
+ status = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (status)
+@@ -304,20 +354,40 @@ resubmit:
+ kit->udev->devpath, status);
+ }
+
++static void do_notify(void *data)
++{
++ struct interfacekit *kit = data;
++ int i;
++ char sysfs_file[8];
++
++ for (i=0; i<kit->ifkit->inputs; i++) {
++ if (test_and_clear_bit(i, &kit->input_events)) {
++ sprintf(sysfs_file, "input%d", i + 1);
++ sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
++ }
++ }
++
++ for (i=0; i<kit->ifkit->sensors; i++) {
++ if (test_and_clear_bit(i, &kit->sensor_events)) {
++ sprintf(sysfs_file, "sensor%d", i + 1);
++ sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
++ }
++ }
++}
++
+ #define show_set_output(value) \
+-static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \
++static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \
+ size_t count) \
+ { \
+ struct usb_interface *intf = to_usb_interface(dev); \
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
++ struct interfacekit *kit = usb_get_intfdata(intf); \
+ int enabled; \
+ int retval; \
+ \
+- if (sscanf(buf, "%d", &enabled) < 1) { \
++ if (sscanf(buf, "%d", &enabled) < 1) \
+ return -EINVAL; \
+- } \
+ \
+- retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \
++ retval = change_outputs(kit, value - 1, enabled); \
+ \
+ return retval ? retval : count; \
+ } \
+@@ -325,9 +395,9 @@ static ssize_t set_output##value(struct
+ static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \
+ { \
+ struct usb_interface *intf = to_usb_interface(dev); \
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
++ struct interfacekit *kit = usb_get_intfdata(intf); \
+ \
+- return sprintf(buf, "%d\n", kit->outputs[value - 1]); \
++ return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
+ } \
+ static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \
+ show_output##value, set_output##value);
+@@ -338,15 +408,23 @@ show_set_output(4);
+ show_set_output(5);
+ show_set_output(6);
+ show_set_output(7);
+-show_set_output(8); /* should be MAX_INTERFACES - 1 */
++show_set_output(8);
++show_set_output(9);
++show_set_output(10);
++show_set_output(11);
++show_set_output(12);
++show_set_output(13);
++show_set_output(14);
++show_set_output(15);
++show_set_output(16);
+
+ #define show_input(value) \
+ static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \
+ { \
+ struct usb_interface *intf = to_usb_interface(dev); \
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
++ struct interfacekit *kit = usb_get_intfdata(intf); \
+ \
+- return sprintf(buf, "%d\n", kit->inputs[value - 1]); \
++ return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \
+ } \
+ static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+
+@@ -357,15 +435,23 @@ show_input(4);
+ show_input(5);
+ show_input(6);
+ show_input(7);
+-show_input(8); /* should be MAX_INTERFACES - 1 */
++show_input(8);
++show_input(9);
++show_input(10);
++show_input(11);
++show_input(12);
++show_input(13);
++show_input(14);
++show_input(15);
++show_input(16);
+
+ #define show_sensor(value) \
+ static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \
+ { \
+ struct usb_interface *intf = to_usb_interface(dev); \
+- struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
++ struct interfacekit *kit = usb_get_intfdata(intf); \
+ \
+- return sprintf(buf, "%d\n", kit->sensors[value - 1]); \
++ return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \
+ } \
+ static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
+
+@@ -376,16 +462,16 @@ show_sensor(4);
+ show_sensor(5);
+ show_sensor(6);
+ show_sensor(7);
+-show_sensor(8); /* should be MAX_INTERFACES - 1 */
++show_sensor(8);
+
+ static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+- struct phidget_interfacekit *kit;
++ struct interfacekit *kit;
+ struct driver_interfacekit *ifkit;
+- int pipe, maxp;
++ int pipe, maxp, rc = -ENOMEM;
+
+ ifkit = (struct driver_interfacekit *)id->driver_info;
+ if (!ifkit)
+@@ -405,29 +491,23 @@ static int interfacekit_probe(struct usb
+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ kit = kzalloc(sizeof(*kit), GFP_KERNEL);
+- if (kit == NULL) {
+- dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__);
+- return -ENOMEM;
+- }
+- kit->ifkit = ifkit;
++ if (!kit)
++ goto out;
+
+- kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma);
+- if (!kit->data) {
+- kfree(kit);
+- return -ENOMEM;
+- }
++ kit->ifkit = ifkit;
++ kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
++ if (!kit->data)
++ goto out;
+
+ kit->irq = usb_alloc_urb(0, GFP_KERNEL);
+- if (!kit->irq) {
+- usb_buffer_free(dev, 8, kit->data, kit->data_dma);
+- kfree(kit);
+- return -ENOMEM;
+- }
++ if (!kit->irq)
++ goto out;
+
+ kit->udev = usb_get_dev(dev);
+ kit->intf = intf;
+- usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
+- (maxp > 8 ? 8 : maxp),
++ INIT_WORK(&kit->do_notify, do_notify, kit);
++ usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
++ maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
+ interfacekit_irq, kit, endpoint->bInterval);
+ kit->irq->transfer_dma = kit->data_dma;
+ kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+@@ -435,7 +515,8 @@ static int interfacekit_probe(struct usb
+ usb_set_intfdata(intf, kit);
+
+ if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
+- return -EIO;
++ rc = -EIO;
++ goto out;
+ }
+
+ if (ifkit->outputs >= 4) {
+@@ -444,12 +525,22 @@ static int interfacekit_probe(struct usb
+ device_create_file(&intf->dev, &dev_attr_output3);
+ device_create_file(&intf->dev, &dev_attr_output4);
+ }
+- if (ifkit->outputs == 8) {
++ if (ifkit->outputs >= 8) {
+ device_create_file(&intf->dev, &dev_attr_output5);
+ device_create_file(&intf->dev, &dev_attr_output6);
+ device_create_file(&intf->dev, &dev_attr_output7);
+ device_create_file(&intf->dev, &dev_attr_output8);
+ }
++ if (ifkit->outputs == 16) {
++ device_create_file(&intf->dev, &dev_attr_output9);
++ device_create_file(&intf->dev, &dev_attr_output10);
++ device_create_file(&intf->dev, &dev_attr_output11);
++ device_create_file(&intf->dev, &dev_attr_output12);
++ device_create_file(&intf->dev, &dev_attr_output13);
++ device_create_file(&intf->dev, &dev_attr_output14);
++ device_create_file(&intf->dev, &dev_attr_output15);
++ device_create_file(&intf->dev, &dev_attr_output16);
++ }
+
+ if (ifkit->inputs >= 4) {
+ device_create_file(&intf->dev, &dev_attr_input1);
+@@ -457,12 +548,22 @@ static int interfacekit_probe(struct usb
+ device_create_file(&intf->dev, &dev_attr_input3);
+ device_create_file(&intf->dev, &dev_attr_input4);
+ }
+- if (ifkit->inputs == 8) {
++ if (ifkit->inputs >= 8) {
+ device_create_file(&intf->dev, &dev_attr_input5);
+ device_create_file(&intf->dev, &dev_attr_input6);
+ device_create_file(&intf->dev, &dev_attr_input7);
+ device_create_file(&intf->dev, &dev_attr_input8);
+ }
++ if (ifkit->inputs == 16) {
++ device_create_file(&intf->dev, &dev_attr_input9);
++ device_create_file(&intf->dev, &dev_attr_input10);
++ device_create_file(&intf->dev, &dev_attr_input11);
++ device_create_file(&intf->dev, &dev_attr_input12);
++ device_create_file(&intf->dev, &dev_attr_input13);
++ device_create_file(&intf->dev, &dev_attr_input14);
++ device_create_file(&intf->dev, &dev_attr_input15);
++ device_create_file(&intf->dev, &dev_attr_input16);
++ }
+
+ if (ifkit->sensors >= 4) {
+ device_create_file(&intf->dev, &dev_attr_sensor1);
+@@ -475,9 +576,8 @@ static int interfacekit_probe(struct usb
+ device_create_file(&intf->dev, &dev_attr_sensor6);
+ device_create_file(&intf->dev, &dev_attr_sensor7);
+ }
+- if (ifkit->sensors == 8) {
++ if (ifkit->sensors == 8)
+ device_create_file(&intf->dev, &dev_attr_sensor8);
+- }
+
+ if (ifkit->has_lcd)
+ device_create_file(&intf->dev, &dev_attr_lcd);
+@@ -486,29 +586,56 @@ static int interfacekit_probe(struct usb
+ ifkit->sensors, ifkit->inputs, ifkit->outputs);
+
+ return 0;
++
++out:
++ if (kit) {
++ if (kit->irq)
++ usb_free_urb(kit->irq);
++ if (kit->data)
++ usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
++ kfree(kit);
++ }
++
++ return rc;
+ }
+
+ static void interfacekit_disconnect(struct usb_interface *interface)
+ {
+- struct phidget_interfacekit *kit;
++ struct interfacekit *kit;
+
+ kit = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+ if (!kit)
+ return;
+
++ usb_kill_urb(kit->irq);
++ usb_free_urb(kit->irq);
++ usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
++
++ cancel_delayed_work(&kit->do_notify);
++
+ if (kit->ifkit->outputs >= 4) {
+ device_remove_file(&interface->dev, &dev_attr_output1);
+ device_remove_file(&interface->dev, &dev_attr_output2);
+ device_remove_file(&interface->dev, &dev_attr_output3);
+ device_remove_file(&interface->dev, &dev_attr_output4);
+ }
+- if (kit->ifkit->outputs == 8) {
++ if (kit->ifkit->outputs >= 8) {
+ device_remove_file(&interface->dev, &dev_attr_output5);
+ device_remove_file(&interface->dev, &dev_attr_output6);
+ device_remove_file(&interface->dev, &dev_attr_output7);
+ device_remove_file(&interface->dev, &dev_attr_output8);
+ }
++ if (kit->ifkit->outputs == 16) {
++ device_remove_file(&interface->dev, &dev_attr_output9);
++ device_remove_file(&interface->dev, &dev_attr_output10);
++ device_remove_file(&interface->dev, &dev_attr_output11);
++ device_remove_file(&interface->dev, &dev_attr_output12);
++ device_remove_file(&interface->dev, &dev_attr_output13);
++ device_remove_file(&interface->dev, &dev_attr_output14);
++ device_remove_file(&interface->dev, &dev_attr_output15);
++ device_remove_file(&interface->dev, &dev_attr_output16);
++ }
+
+ if (kit->ifkit->inputs >= 4) {
+ device_remove_file(&interface->dev, &dev_attr_input1);
+@@ -516,12 +643,22 @@ static void interfacekit_disconnect(stru
+ device_remove_file(&interface->dev, &dev_attr_input3);
+ device_remove_file(&interface->dev, &dev_attr_input4);
+ }
+- if (kit->ifkit->inputs == 8) {
++ if (kit->ifkit->inputs >= 8) {
+ device_remove_file(&interface->dev, &dev_attr_input5);
+ device_remove_file(&interface->dev, &dev_attr_input6);
+ device_remove_file(&interface->dev, &dev_attr_input7);
+ device_remove_file(&interface->dev, &dev_attr_input8);
+ }
++ if (kit->ifkit->inputs == 16) {
++ device_remove_file(&interface->dev, &dev_attr_input9);
++ device_remove_file(&interface->dev, &dev_attr_input10);
++ device_remove_file(&interface->dev, &dev_attr_input11);
++ device_remove_file(&interface->dev, &dev_attr_input12);
++ device_remove_file(&interface->dev, &dev_attr_input13);
++ device_remove_file(&interface->dev, &dev_attr_input14);
++ device_remove_file(&interface->dev, &dev_attr_input15);
++ device_remove_file(&interface->dev, &dev_attr_input16);
++ }
+
+ if (kit->ifkit->sensors >= 4) {
+ device_remove_file(&interface->dev, &dev_attr_sensor1);
+@@ -534,19 +671,15 @@ static void interfacekit_disconnect(stru
+ device_remove_file(&interface->dev, &dev_attr_sensor6);
+ device_remove_file(&interface->dev, &dev_attr_sensor7);
+ }
+- if (kit->ifkit->sensors == 8) {
++ if (kit->ifkit->sensors == 8)
+ device_remove_file(&interface->dev, &dev_attr_sensor8);
+- }
++
+ if (kit->ifkit->has_lcd)
+ device_remove_file(&interface->dev, &dev_attr_lcd);
+
+ dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
+ kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
+
+- usb_kill_urb(kit->irq);
+- usb_free_urb(kit->irq);
+- usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma);
+-
+ usb_put_dev(kit->udev);
+ kfree(kit);
+ }
diff --git a/usb/usb-shuttle_usbat-fix-handling-of-scatter-gather-buffers.patch b/usb/usb-shuttle_usbat-fix-handling-of-scatter-gather-buffers.patch
new file mode 100644
index 00000000000000..b3eca6fdc7c3c8
--- /dev/null
+++ b/usb/usb-shuttle_usbat-fix-handling-of-scatter-gather-buffers.patch
@@ -0,0 +1,221 @@
+From dsd@ntlworld.com Tue May 2 10:30:13 2006
+From: Daniel Drake <dsd@gentoo.org>
+To: greg@kroah.com
+Cc: usb-storage@lists.one-eyed-alien.net
+Cc: linux-usb-devel@lists.sourceforge.net
+Cc: mdharm-usb@one-eyed-alien.net
+Cc: peterc@gelato.unsw.edu.au
+Subject: USB: shuttle_usbat: Fix handling of scatter-gather buffers
+Message-Id: <20060502173012.7540E88810C@zog.reactivated.net>
+Date: Tue, 2 May 2006 18:30:12 +0100 (BST)
+
+From: Peter Chubb <peterc@gelato.unsw.edu.au>
+
+I've worked out what's going wrong. The scsi layer is now much
+more likely to pass down scatterlists instead of plain buffers. So
+you have to make sure that they're handled correctly. In one of the
+changes along the way, usbat_write_block and friends stopped obeying
+the srb->use_sg flag.
+
+Anyway, with the appended patch, and the one I'm putting in the next email, it
+all seems to work for the HP cd4e. Of course, someone's going to have
+to test it with the flash drives as well....
+
+
+This patch teaches the usbat_{read,write}_block functions to
+obey the use_sg flag in the scsi-request.
+
+Signed-off-by: Peter Chubb <peterc@gelato.unsw.edu.au>
+Signed-off-by: Daniel Drake <dsd@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/storage/shuttle_usbat.c | 54 ++++++++++++++++++++----------------
+ 1 file changed, 30 insertions(+), 24 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/storage/shuttle_usbat.c
++++ gregkh-2.6/drivers/usb/storage/shuttle_usbat.c
+@@ -131,28 +131,30 @@ static int usbat_write(struct us_data *u
+ * Convenience function to perform a bulk read
+ */
+ static int usbat_bulk_read(struct us_data *us,
+- unsigned char *data,
+- unsigned int len)
++ unsigned char *data,
++ unsigned int len,
++ int use_sg)
+ {
+ if (len == 0)
+ return USB_STOR_XFER_GOOD;
+
+ US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+- return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL);
++ return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL);
+ }
+
+ /*
+ * Convenience function to perform a bulk write
+ */
+ static int usbat_bulk_write(struct us_data *us,
+- unsigned char *data,
+- unsigned int len)
++ unsigned char *data,
++ unsigned int len,
++ int use_sg)
+ {
+ if (len == 0)
+ return USB_STOR_XFER_GOOD;
+
+ US_DEBUGP("usbat_bulk_write: len = %d\n", len);
+- return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL);
++ return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL);
+ }
+
+ /*
+@@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us
+ */
+ static int usbat_read_block(struct us_data *us,
+ unsigned char *content,
+- unsigned short len)
++ unsigned short len,
++ int use_sg)
+ {
+ int result;
+ unsigned char *command = us->iobuf;
+@@ -338,7 +341,7 @@ static int usbat_read_block(struct us_da
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+- result = usbat_bulk_read(us, content, len);
++ result = usbat_bulk_read(us, content, len, use_sg);
+ return (result == USB_STOR_XFER_GOOD ?
+ USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+ }
+@@ -350,7 +353,8 @@ static int usbat_write_block(struct us_d
+ unsigned char access,
+ unsigned char *content,
+ unsigned short len,
+- int minutes)
++ int minutes,
++ int use_sg)
+ {
+ int result;
+ unsigned char *command = us->iobuf;
+@@ -372,7 +376,7 @@ static int usbat_write_block(struct us_d
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+- result = usbat_bulk_write(us, content, len);
++ result = usbat_bulk_write(us, content, len, use_sg);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+@@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(s
+ data[1+(j<<1)] = data_out[j];
+ }
+
+- result = usbat_bulk_write(us, data, num_registers*2);
++ result = usbat_bulk_write(us, data, num_registers*2, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+@@ -583,7 +587,7 @@ static int usbat_multiple_write(struct u
+ }
+
+ /* Send the data */
+- result = usbat_bulk_write(us, data, num_registers*2);
++ result = usbat_bulk_write(us, data, num_registers*2, 0);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+@@ -606,8 +610,9 @@ static int usbat_multiple_write(struct u
+ * other related details) are defined beforehand with _set_shuttle_features().
+ */
+ static int usbat_read_blocks(struct us_data *us,
+- unsigned char *buffer,
+- int len)
++ unsigned char *buffer,
++ int len,
++ int use_sg)
+ {
+ int result;
+ unsigned char *command = us->iobuf;
+@@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_d
+ return USB_STOR_TRANSPORT_FAILED;
+
+ /* Read the blocks we just asked for */
+- result = usbat_bulk_read(us, buffer, len);
++ result = usbat_bulk_read(us, buffer, len, use_sg);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+@@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_d
+ */
+ static int usbat_write_blocks(struct us_data *us,
+ unsigned char *buffer,
+- int len)
++ int len,
++ int use_sg)
+ {
+ int result;
+ unsigned char *command = us->iobuf;
+@@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_
+ return USB_STOR_TRANSPORT_FAILED;
+
+ /* Write the data */
+- result = usbat_bulk_write(us, buffer, len);
++ result = usbat_bulk_write(us, buffer, len, use_sg);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+@@ -947,7 +953,7 @@ static int usbat_flash_get_sector_count(
+ msleep(100);
+
+ /* Read the device identification data */
+- rc = usbat_read_block(us, reply, 512);
++ rc = usbat_read_block(us, reply, 512, 0);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+@@ -1031,7 +1037,7 @@ static int usbat_flash_read_data(struct
+ goto leave;
+
+ /* Read the data we just requested */
+- result = usbat_read_blocks(us, buffer, len);
++ result = usbat_read_blocks(us, buffer, len, 0);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+@@ -1125,7 +1131,7 @@ static int usbat_flash_write_data(struct
+ goto leave;
+
+ /* Write the data */
+- result = usbat_write_blocks(us, buffer, len);
++ result = usbat_write_blocks(us, buffer, len, 0);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+@@ -1503,10 +1509,10 @@ static int usbat_hp8200e_transport(struc
+ * AT SPEED 4 IS UNRELIABLE!!!
+ */
+
+- if ( (result = usbat_write_block(us,
++ if ((result = usbat_write_block(us,
+ USBAT_ATA, srb->cmnd, 12,
+- srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
+- USB_STOR_TRANSPORT_GOOD) {
++ (srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) !=
++ USB_STOR_TRANSPORT_GOOD)) {
+ return result;
+ }
+
+@@ -1533,7 +1539,7 @@ static int usbat_hp8200e_transport(struc
+ len = *status;
+
+
+- result = usbat_read_block(us, srb->request_buffer, len);
++ result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg);
+
+ /* Debug-print the first 32 bytes of the transfer */
+
diff --git a/usb/usb-shuttle_usbat-hardcode-detection-of-hp-cdrw-devices.patch b/usb/usb-shuttle_usbat-hardcode-detection-of-hp-cdrw-devices.patch
new file mode 100644
index 00000000000000..f68604282250b4
--- /dev/null
+++ b/usb/usb-shuttle_usbat-hardcode-detection-of-hp-cdrw-devices.patch
@@ -0,0 +1,170 @@
+From dsd@ntlworld.com Tue May 2 12:30:26 2006
+From: Daniel Drake <dsd@gentoo.org>
+To: greg@kroah.com
+Cc: usb-storage@lists.one-eyed-alien.net
+Cc: linux-usb-devel@lists.sourceforge.net
+Cc: mdharm-usb@one-eyed-alien.net
+Cc: peterc@gelato.unsw.edu.au
+Subject: USB: shuttle_usbat: Hardcode detection of HP CDRW devices
+Message-Id: <20060502172934.9558888810C@zog.reactivated.net>
+Date: Tue, 2 May 2006 18:29:34 +0100 (BST)
+
+From: Peter Chubb <peterc@gelato.unsw.edu.au>
+
+Use USB vendor and product IDs to determine whether the attached
+device is a CDROM or a Flash device. Daniel Drake says that the
+*same* vendor and product IDs for non-HP vendor ID could be either
+flash or cdrom, so try to probe for them.
+
+Signed-off-by: Peter Chubb <peterc@gelato.unsw.edu.au>
+Signed-off-by: Daniel Drake <dsd@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/storage/shuttle_usbat.c | 51 +++++++++++++++++++++++++-----------
+ drivers/usb/storage/shuttle_usbat.h | 4 ++
+ drivers/usb/storage/unusual_devs.h | 8 ++---
+ 3 files changed, 43 insertions(+), 20 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/storage/shuttle_usbat.c
++++ gregkh-2.6/drivers/usb/storage/shuttle_usbat.c
+@@ -893,22 +893,28 @@ static int usbat_identify_device(struct
+ * Set the transport function based on the device type
+ */
+ static int usbat_set_transport(struct us_data *us,
+- struct usbat_info *info)
++ struct usbat_info *info,
++ int devicetype)
+ {
+- int rc;
+
+- if (!info->devicetype) {
+- rc = usbat_identify_device(us, info);
+- if (rc != USB_STOR_TRANSPORT_GOOD) {
+- US_DEBUGP("usbat_set_transport: Could not identify device\n");
+- return 1;
+- }
+- }
++ if (!info->devicetype)
++ info->devicetype = devicetype;
++
++ if (!info->devicetype)
++ usbat_identify_device(us, info);
++
++ switch (info->devicetype) {
++ default:
++ return USB_STOR_TRANSPORT_ERROR;
+
+- if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
++ case USBAT_DEV_HP8200:
+ us->transport = usbat_hp8200e_transport;
+- else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
++ break;
++
++ case USBAT_DEV_FLASH:
+ us->transport = usbat_flash_transport;
++ break;
++ }
+
+ return 0;
+ }
+@@ -1316,7 +1322,7 @@ static int usbat_select_and_test_registe
+ /*
+ * Initialize the USBAT processor and the storage device
+ */
+-int init_usbat(struct us_data *us)
++static int init_usbat(struct us_data *us, int devicetype)
+ {
+ int rc;
+ struct usbat_info *info;
+@@ -1398,7 +1404,7 @@ int init_usbat(struct us_data *us)
+ US_DEBUGP("INIT 9\n");
+
+ /* At this point, we need to detect which device we are using */
+- if (usbat_set_transport(us, info))
++ if (usbat_set_transport(us, info, devicetype))
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUGP("INIT 10\n");
+@@ -1701,6 +1707,22 @@ static int usbat_flash_transport(struct
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
++int init_usbat_cd(struct us_data *us)
++{
++ return init_usbat(us, USBAT_DEV_HP8200);
++}
++
++
++int init_usbat_flash(struct us_data *us)
++{
++ return init_usbat(us, USBAT_DEV_FLASH);
++}
++
++int init_usbat_probe(struct us_data *us)
++{
++ return init_usbat(us, 0);
++}
++
+ /*
+ * Default transport function. Attempts to detect which transport function
+ * should be called, makes it the new default, and calls it.
+@@ -1714,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *sr
+ {
+ struct usbat_info *info = (struct usbat_info*) (us->extra);
+
+- if (usbat_set_transport(us, info))
++ if (usbat_set_transport(us, info, 0))
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return us->transport(srb, us);
+ }
+-
+--- gregkh-2.6.orig/drivers/usb/storage/shuttle_usbat.h
++++ gregkh-2.6/drivers/usb/storage/shuttle_usbat.h
+@@ -106,7 +106,9 @@
+ #define USBAT_FEAT_ET2 0x01
+
+ extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int init_usbat(struct us_data *us);
++extern int init_usbat_cd(struct us_data *us);
++extern int init_usbat_flash(struct us_data *us);
++extern int init_usbat_probe(struct us_data *us);
+
+ struct usbat_info {
+ int devicetype;
+--- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h
++++ gregkh-2.6/drivers/usb/storage/unusual_devs.h
+@@ -78,12 +78,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x
+ UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
+ "HP",
+ "CD-Writer+ 8200e",
+- US_SC_8070, US_PR_USBAT, init_usbat, 0),
++ US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+
+ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
+ "HP",
+ "CD-Writer+ CD-4e",
+- US_SC_8070, US_PR_USBAT, init_usbat, 0),
++ US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+ #endif
+
+ /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+@@ -393,7 +393,7 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x
+ UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999,
+ "Shuttle/SCM",
+ "USBAT-02",
+- US_SC_SCSI, US_PR_USBAT, init_usbat,
++ US_SC_SCSI, US_PR_USBAT, init_usbat_probe,
+ US_FL_SINGLE_LUN),
+ #endif
+
+@@ -797,7 +797,7 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x
+ UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005,
+ "Sandisk",
+ "ImageMate SDDR-05b",
+- US_SC_SCSI, US_PR_USBAT, init_usbat,
++ US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+ US_FL_SINGLE_LUN ),
+ #endif
+
diff --git a/usb/usb-ub-oops-in-block_uevent.patch b/usb/usb-ub-oops-in-block_uevent.patch
new file mode 100644
index 00000000000000..4710adca9b306e
--- /dev/null
+++ b/usb/usb-ub-oops-in-block_uevent.patch
@@ -0,0 +1,72 @@
+From zaitcev@redhat.com Wed May 3 00:16:11 2006
+Date: Wed, 3 May 2006 00:16:00 -0700
+From: Pete Zaitcev <zaitcev@redhat.com>
+To: greg@kroah.com
+Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net
+Subject: USB: ub oops in block_uevent
+Message-Id: <20060503001600.c9012512.zaitcev@redhat.com>
+
+In kernel 2.6.16, if a mounted storage device is removed, an oops happens
+because ub supplies an interface device (and kobject) to the block layer,
+but neglects to pin it. And apparently, the block layer expects its users
+to pin device structures.
+
+The code in ub was broken this way for years. But the bug was exposed only
+by 2.6.16 when it started to call block_uevent on close, which traverses
+device structures (kobjects actually).
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/block/ub.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- gregkh-2.6.orig/drivers/block/ub.c
++++ gregkh-2.6/drivers/block/ub.c
+@@ -534,6 +534,9 @@ static void ub_cleanup(struct ub_dev *sc
+ kfree(lun);
+ }
+
++ usb_set_intfdata(sc->intf, NULL);
++ usb_put_intf(sc->intf);
++ usb_put_dev(sc->dev);
+ kfree(sc);
+ }
+
+@@ -2215,7 +2218,12 @@ static int ub_probe(struct usb_interface
+ // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+ usb_set_intfdata(intf, sc);
+ usb_get_dev(sc->dev);
+- // usb_get_intf(sc->intf); /* Do we need this? */
++ /*
++ * Since we give the interface struct to the block level through
++ * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
++ * oopses on close after a disconnect (kernels 2.6.16 and up).
++ */
++ usb_get_intf(sc->intf);
+
+ snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
+ sc->dev->bus->busnum, sc->dev->devnum);
+@@ -2280,7 +2288,7 @@ static int ub_probe(struct usb_interface
+
+ err_dev_desc:
+ usb_set_intfdata(intf, NULL);
+- // usb_put_intf(sc->intf);
++ usb_put_intf(sc->intf);
+ usb_put_dev(sc->dev);
+ kfree(sc);
+ err_core:
+@@ -2454,12 +2462,6 @@ static void ub_disconnect(struct usb_int
+ * and no URBs left in transit.
+ */
+
+- usb_set_intfdata(intf, NULL);
+- // usb_put_intf(sc->intf);
+- sc->intf = NULL;
+- usb_put_dev(sc->dev);
+- sc->dev = NULL;
+-
+ ub_put(sc);
+ }
+
diff --git a/usb/usb-usbcore-don-t-check-the-device-s-power-source.patch b/usb/usb-usbcore-don-t-check-the-device-s-power-source.patch
new file mode 100644
index 00000000000000..a2d2b058e444ba
--- /dev/null
+++ b/usb/usb-usbcore-don-t-check-the-device-s-power-source.patch
@@ -0,0 +1,68 @@
+From stern@rowland.harvard.edu Tue May 2 12:22:49 2006
+Date: Tue, 2 May 2006 15:22:41 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: USB development list <linux-usb-devel@lists.sourceforge.net>
+Subject: USB: usbcore: don't check the device's power source
+Message-ID: <Pine.LNX.4.44L0.0605021517030.1170-100000@iolanthe.rowland.org>
+
+The choose_configuration() routine contains code the determine the
+device's power source, so that configurations requiring external power
+can be ruled out if the device is running on bus power. Unfortunately
+it turns out that some devices have errors in their config descriptors
+and other devices don't like the GET_DEVICE_STATUS request.
+
+Since that information wasn't used for anything else, this patch (as673)
+removes the code, leaving only a comment. It fixes bugzilla entry
+#6448.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/core/hub.c | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/core/hub.c
++++ gregkh-2.6/drivers/usb/core/hub.c
+@@ -1175,19 +1175,9 @@ static inline const char *plural(int n)
+ static int choose_configuration(struct usb_device *udev)
+ {
+ int i;
+- u16 devstatus;
+- int bus_powered;
+ int num_configs;
+ struct usb_host_config *c, *best;
+
+- /* If this fails, assume the device is bus-powered */
+- devstatus = 0;
+- usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+- le16_to_cpus(&devstatus);
+- bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
+- dev_dbg(&udev->dev, "device is %s-powered\n",
+- bus_powered ? "bus" : "self");
+-
+ best = NULL;
+ c = udev->config;
+ num_configs = udev->descriptor.bNumConfigurations;
+@@ -1204,6 +1194,19 @@ static int choose_configuration(struct u
+ * similar errors in their descriptors. If the next test
+ * were allowed to execute, such configurations would always
+ * be rejected and the devices would not work as expected.
++ * In the meantime, we run the risk of selecting a config
++ * that requires external power at a time when that power
++ * isn't available. It seems to be the lesser of two evils.
++ *
++ * Bugzilla #6448 reports a device that appears to crash
++ * when it receives a GET_DEVICE_STATUS request! We don't
++ * have any other way to tell whether a device is self-powered,
++ * but since we don't use that information anywhere but here,
++ * the call has been removed.
++ *
++ * Maybe the GET_DEVICE_STATUS call and the test below can
++ * be reinstated when device firmwares become more reliable.
++ * Don't hold your breath.
+ */
+ #if 0
+ /* Rule out self-powered configs for a bus-powered device */