diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-05-04 16:43:43 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-05-04 16:43:43 -0700 |
commit | eedb5a80e5779bb431e036a85ce268d2f9898e04 (patch) | |
tree | 3ecd64b67bbf50b5841229a21aeed38c52751c9a /usb | |
parent | c254ef31aea65814b54e8eed48108856450ebe04 (diff) | |
download | patches-eedb5a80e5779bb431e036a85ce268d2f9898e04.tar.gz |
usb and pci patches added
Diffstat (limited to 'usb')
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 */ |