aboutsummaryrefslogtreecommitdiffstats
path: root/usb.current
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 14:05:20 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 14:05:20 -0700
commit8cd954e9929a6cd5e42f25d91ce1e3e0a6365084 (patch)
tree3fe03302ae2b5d2dd87d55e7771eeb4af48f2fd6 /usb.current
parent25cc1b6cfc1a7af9fdf8ab54c0f6fad37897d9e7 (diff)
downloadpatches-8cd954e9929a6cd5e42f25d91ce1e3e0a6365084.tar.gz
a bunch of bugfixes
Diffstat (limited to 'usb.current')
-rw-r--r--usb.current/usb-cdc-acm-fix-stupid-null-pointer-in-resume.patch30
-rw-r--r--usb.current/usb-ehci-adjust-ehci_iso_stream-for-changes-in-ehci_qh.patch68
-rw-r--r--usb.current/usb-ehci-fix-itd-list-order.patch62
-rw-r--r--usb.current/usb-fix-usbfs-regression.patch57
-rw-r--r--usb.current/usb-option-add-support-for-a-variant-of-dlink-dwm-652-u5.patch47
-rw-r--r--usb.current/usb-serial-fix-error-message-on-close-in-generic-driver.patch36
-rw-r--r--usb.current/usb-serial-fix-softint-not-being-called-on-errors.patch50
-rw-r--r--usb.current/usb-serial-use-port-endpoint-size-to-determine-if-ep-is-available.patch115
-rw-r--r--usb.current/usb-unusual_devs.h-fix-capacity-for-sl11r-ide-2.6c.patch47
9 files changed, 512 insertions, 0 deletions
diff --git a/usb.current/usb-cdc-acm-fix-stupid-null-pointer-in-resume.patch b/usb.current/usb-cdc-acm-fix-stupid-null-pointer-in-resume.patch
new file mode 100644
index 00000000000000..61357bc135c715
--- /dev/null
+++ b/usb.current/usb-cdc-acm-fix-stupid-null-pointer-in-resume.patch
@@ -0,0 +1,30 @@
+From oliver@neukum.org Mon Mar 15 13:32:58 2010
+From: Oliver Neukum <oliver@neukum.org>
+Date: Wed, 3 Mar 2010 00:37:56 +0100
+Subject: USB: cdc-acm: Fix stupid NULL pointer in resume()
+To: Greg KH <greg@kroah.com>
+Cc: Rickard Bellini <rickard.bellini@ericsson.com>, linux-usb@vger.kernel.org, stable@kernel.org
+Message-ID: <201003030037.56242.oliver@neukum.org>
+
+
+Stupid logic bug passing a just nulled pointer
+
+Signed-off-by: Oliver Neukum <neukum@b1-systems.de>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interfa
+ wb = acm->delayed_wb;
+ acm->delayed_wb = NULL;
+ spin_unlock_irq(&acm->write_lock);
+- acm_start_wb(acm, acm->delayed_wb);
++ acm_start_wb(acm, wb);
+ } else {
+ spin_unlock_irq(&acm->write_lock);
+ }
diff --git a/usb.current/usb-ehci-adjust-ehci_iso_stream-for-changes-in-ehci_qh.patch b/usb.current/usb-ehci-adjust-ehci_iso_stream-for-changes-in-ehci_qh.patch
new file mode 100644
index 00000000000000..afc358d0e5a043
--- /dev/null
+++ b/usb.current/usb-ehci-adjust-ehci_iso_stream-for-changes-in-ehci_qh.patch
@@ -0,0 +1,68 @@
+From clemens@ladisch.de Mon Mar 15 13:19:09 2010
+From: Clemens Ladisch <clemens@ladisch.de>
+Date: Mon, 01 Mar 2010 17:18:56 +0100
+Subject: USB: EHCI: adjust ehci_iso_stream for changes in ehci_qh
+To: Alan Stern <stern@rowland.harvard.edu>
+Cc: linux-usb@vger.kernel.org, David Brownell <dbrownell@users.sourceforge.net>, Alek Du <alek.du@intel.com>, Colin Fletcher <colin.m.fletcher@googlemail.com>
+Message-ID: <4B8BE8F0.4050508@ladisch.de>
+
+The EHCI driver stores in usb_host_endpoint.hcpriv a pointer to either
+an ehci_qh or an ehci_iso_stream structure, and uses the contents of the
+hw_info1 field to distinguish the two cases.
+
+After ehci_qh was split into hw and sw parts, ehci_iso_stream must also
+be adjusted so that it again looks like an ehci_qh structure.
+
+This fixes a NULL pointer access in ehci_endpoint_disable() when it
+tries to access qh->hw->hw_info1.
+
+Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
+Reported-by: Colin Fletcher <colin.m.fletcher@googlemail.com>
+Cc: stable <stable@kernel.org>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-hcd.c | 2 +-
+ drivers/usb/host/ehci-sched.c | 4 ++--
+ drivers/usb/host/ehci.h | 5 ++---
+ 3 files changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -995,7 +995,7 @@ rescan:
+ /* endpoints can be iso streams. for now, we don't
+ * accelerate iso completions ... so spin a while.
+ */
+- if (qh->hw->hw_info1 == 0) {
++ if (qh->hw == NULL) {
+ ehci_vdbg (ehci, "iso delay\n");
+ goto idle_timeout;
+ }
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci,
+ urb->interval);
+ }
+
+- /* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */
+- } else if (unlikely (stream->hw_info1 != 0)) {
++ /* if dev->ep [epnum] is a QH, hw is set */
++ } else if (unlikely (stream->hw != NULL)) {
+ ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
+ urb->dev->devpath, epnum,
+ usb_pipein(urb->pipe) ? "in" : "out");
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -394,9 +394,8 @@ struct ehci_iso_sched {
+ * acts like a qh would, if EHCI had them for ISO.
+ */
+ struct ehci_iso_stream {
+- /* first two fields match QH, but info1 == 0 */
+- __hc32 hw_next;
+- __hc32 hw_info1;
++ /* first field matches ehci_hq, but is NULL */
++ struct ehci_qh_hw *hw;
+
+ u32 refcount;
+ u8 bEndpointAddress;
diff --git a/usb.current/usb-ehci-fix-itd-list-order.patch b/usb.current/usb-ehci-fix-itd-list-order.patch
new file mode 100644
index 00000000000000..b6928d3ba67994
--- /dev/null
+++ b/usb.current/usb-ehci-fix-itd-list-order.patch
@@ -0,0 +1,62 @@
+From clemens@ladisch.de Mon Mar 15 13:18:20 2010
+From: Clemens Ladisch <clemens@ladisch.de>
+Date: Mon, 01 Mar 2010 09:12:50 +0100
+Subject: USB: EHCI: fix ITD list order
+To: linux-usb@vger.kernel.org, David Brownell <dbrownell@users.sourceforge.net>
+Cc: Colin Fletcher <colin.m.fletcher@googlemail.com>
+Message-ID: <4B8B7702.4050107@ladisch.de>
+
+
+When isochronous URBs are shorter than one frame and when more than one
+ITD in a frame has been completed before the interrupt can be handled,
+scan_periodic() completes the URBs in the order in which they are found
+in the descriptor list. Therefore, the descriptor list must contain the
+ITDs in the correct order, i.e., a new ITD must be linked in after any
+previous ITDs of the same endpoint.
+
+This should fix garbled capture data in the USB audio drivers.
+
+Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
+Reported-by: Colin Fletcher <colin.m.fletcher@googlemail.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-sched.c | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1565,13 +1565,27 @@ itd_patch(
+ static inline void
+ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
+ {
+- /* always prepend ITD/SITD ... only QH tree is order-sensitive */
+- itd->itd_next = ehci->pshadow [frame];
+- itd->hw_next = ehci->periodic [frame];
+- ehci->pshadow [frame].itd = itd;
++ union ehci_shadow *prev = &ehci->pshadow[frame];
++ __hc32 *hw_p = &ehci->periodic[frame];
++ union ehci_shadow here = *prev;
++ __hc32 type = 0;
++
++ /* skip any iso nodes which might belong to previous microframes */
++ while (here.ptr) {
++ type = Q_NEXT_TYPE(ehci, *hw_p);
++ if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
++ break;
++ prev = periodic_next_shadow(ehci, prev, type);
++ hw_p = shadow_next_periodic(ehci, &here, type);
++ here = *prev;
++ }
++
++ itd->itd_next = here;
++ itd->hw_next = *hw_p;
++ prev->itd = itd;
+ itd->frame = frame;
+ wmb ();
+- ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
++ *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
+ }
+
+ /* fit urb's itds into the selected schedule slot; activate as needed */
diff --git a/usb.current/usb-fix-usbfs-regression.patch b/usb.current/usb-fix-usbfs-regression.patch
new file mode 100644
index 00000000000000..10275a4b7ff7bf
--- /dev/null
+++ b/usb.current/usb-fix-usbfs-regression.patch
@@ -0,0 +1,57 @@
+From stern@rowland.harvard.edu Mon Mar 15 13:13:23 2010
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Sat, 6 Mar 2010 15:04:03 -0500 (EST)
+Subject: USB: fix usbfs regression
+To: Greg KH <greg@kroah.com>
+Cc: Markus Rechberger <mrechberger@gmail.com>, <werner@guyane.dyn-o-saur.com>, Marcus Meissner <meissner@suse.de>
+Message-ID: <Pine.LNX.4.44L0.1003061459500.22767-100000@netrider.rowland.org>
+
+
+This patch (as1352) fixes a bug in the way isochronous input data is
+returned to userspace for usbfs transfers. The entire buffer must be
+copied, not just the first actual_length bytes, because the individual
+packets will be discontiguous if any of them are short.
+
+Reported-by: Markus Rechberger <mrechberger@gmail.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devio.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_
+ free_async(as);
+ return -ENOMEM;
+ }
++ /* Isochronous input data may end up being discontiguous
++ * if some of the packets are short. Clear the buffer so
++ * that the gaps don't leak kernel data to userspace.
++ */
++ if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
++ memset(as->urb->transfer_buffer, 0,
++ uurb->buffer_length);
+ }
+ as->urb->dev = ps->dev;
+ as->urb->pipe = (uurb->type << 30) |
+@@ -1345,10 +1352,14 @@ static int processcompl(struct async *as
+ void __user *addr = as->userurb;
+ unsigned int i;
+
+- if (as->userbuffer && urb->actual_length)
+- if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+- urb->actual_length))
++ if (as->userbuffer && urb->actual_length) {
++ if (urb->number_of_packets > 0) /* Isochronous */
++ i = urb->transfer_buffer_length;
++ else /* Non-Isoc */
++ i = urb->actual_length;
++ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
+ goto err_out;
++ }
+ if (put_user(as->status, &userurb->status))
+ goto err_out;
+ if (put_user(urb->actual_length, &userurb->actual_length))
diff --git a/usb.current/usb-option-add-support-for-a-variant-of-dlink-dwm-652-u5.patch b/usb.current/usb-option-add-support-for-a-variant-of-dlink-dwm-652-u5.patch
new file mode 100644
index 00000000000000..70e2cf5f45d038
--- /dev/null
+++ b/usb.current/usb-option-add-support-for-a-variant-of-dlink-dwm-652-u5.patch
@@ -0,0 +1,47 @@
+From huang.ying.caritas@gmail.com Mon Mar 15 13:17:47 2010
+From: Huang Ying <huang.ying.caritas@gmail.com>
+Date: Sun, 28 Feb 2010 13:51:29 +0800
+Subject: USB: Option: Add support for a variant of DLink DWM 652 U5
+To: Greg KH <gregkh@suse.de>
+Message-ID: <1267336289.9610.2.camel@caritas-mobile.ml.org>
+
+
+I found a DLink DWM 652 U5 USB 3G modem has product ID 0xce1e instead
+of orignal 0xce16. The new ID is added.
+
+And I found there are two entries for 0xce16, one has raw number, the
+other has symbol DLINK_PRODUCT_DWM_652_U5. This is fixed too.
+
+Signed-off-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -309,6 +309,7 @@ static int option_resume(struct usb_ser
+ #define DLINK_VENDOR_ID 0x1186
+ #define DLINK_PRODUCT_DWM_652 0x3e04
+ #define DLINK_PRODUCT_DWM_652_U5 0xce16
++#define DLINK_PRODUCT_DWM_652_U5A 0xce1e
+
+ #define QISDA_VENDOR_ID 0x1da5
+ #define QISDA_PRODUCT_H21_4512 0x4512
+@@ -659,6 +660,7 @@ static const struct usb_device_id option
+ { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+ { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
+ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
++ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5A) },
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
+@@ -666,7 +668,6 @@ static const struct usb_device_id option
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
+ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+- { USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
+ { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
diff --git a/usb.current/usb-serial-fix-error-message-on-close-in-generic-driver.patch b/usb.current/usb-serial-fix-error-message-on-close-in-generic-driver.patch
new file mode 100644
index 00000000000000..a70c4105e9d4b3
--- /dev/null
+++ b/usb.current/usb-serial-fix-error-message-on-close-in-generic-driver.patch
@@ -0,0 +1,36 @@
+From jhovold@gmail.com Mon Mar 15 13:14:47 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Sat, 27 Feb 2010 14:05:46 +0100
+Subject: USB: serial: fix error message on close in generic driver
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1267275946-31463-1-git-send-email-jhovold@gmail.com>
+
+
+Resubmitting read urb fails with -EPERM if completion handler runs while
+urb is being killed on close. This should not be reported as an error.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/generic.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -415,11 +415,13 @@ void usb_serial_generic_resubmit_read_ur
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ usb_serial_generic_read_bulk_callback), port);
++
+ result = usb_submit_urb(urb, mem_flags);
+- if (result)
++ if (result && result != -EPERM) {
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
++ }
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb);
+
diff --git a/usb.current/usb-serial-fix-softint-not-being-called-on-errors.patch b/usb.current/usb-serial-fix-softint-not-being-called-on-errors.patch
new file mode 100644
index 00000000000000..fef41950a1bb0b
--- /dev/null
+++ b/usb.current/usb-serial-fix-softint-not-being-called-on-errors.patch
@@ -0,0 +1,50 @@
+From jhovold@gmail.com Mon Mar 15 13:15:18 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Sat, 27 Feb 2010 14:06:07 +0100
+Subject: USB: serial: fix softint not being called on errors
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1267275967-31534-1-git-send-email-jhovold@gmail.com>
+
+
+Make sure usb_serial_port_softint is called on errors also when using
+multi urb writes.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/generic.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -500,23 +500,18 @@ void usb_serial_generic_write_bulk_callb
+ if (port->urbs_in_flight < 0)
+ port->urbs_in_flight = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
+-
+- if (status) {
+- dbg("%s - nonzero multi-urb write bulk status "
+- "received: %d", __func__, status);
+- return;
+- }
+ } else {
+ port->write_urb_busy = 0;
+
+- if (status) {
+- dbg("%s - nonzero multi-urb write bulk status "
+- "received: %d", __func__, status);
++ if (status)
+ kfifo_reset_out(&port->write_fifo);
+- } else
++ else
+ usb_serial_generic_write_start(port);
+ }
+
++ if (status)
++ dbg("%s - non-zero urb status: %d", __func__, status);
++
+ usb_serial_port_softint(port);
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
diff --git a/usb.current/usb-serial-use-port-endpoint-size-to-determine-if-ep-is-available.patch b/usb.current/usb-serial-use-port-endpoint-size-to-determine-if-ep-is-available.patch
new file mode 100644
index 00000000000000..e0b991573bb3a0
--- /dev/null
+++ b/usb.current/usb-serial-use-port-endpoint-size-to-determine-if-ep-is-available.patch
@@ -0,0 +1,115 @@
+From jhovold@gmail.com Mon Mar 15 13:15:47 2010
+From: Johan Hovold <jhovold@gmail.com>
+Date: Sat, 27 Feb 2010 16:24:49 +0100
+Subject: USB: serial: use port endpoint size to determine if ep is available
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>
+Message-ID: <1267284289-21866-1-git-send-email-jhovold@gmail.com>
+
+
+It is possible to have a multi-port device with a port lacking an in or
+out bulk endpoint. Only checking for num_bulk_in or num_bulk_out is thus not
+sufficient to determine whether a specific port has an in or out bulk
+endpoint.
+
+This fixes potential null pointer dereferences in the generic open and
+write routines, as well as access to uninitialised fifo in write_room
+and chars_in_buffer.
+
+Also let write fail with ENODEV (instead of 0) on missing out endpoint
+(also on zero-length writes).
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/generic.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -130,7 +130,7 @@ int usb_serial_generic_open(struct tty_s
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* if we have a bulk endpoint, start reading from it */
+- if (serial->num_bulk_in) {
++ if (port->bulk_in_size) {
+ /* Start reading from the device */
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+@@ -159,10 +159,10 @@ static void generic_cleanup(struct usb_s
+ dbg("%s - port %d", __func__, port->number);
+
+ if (serial->dev) {
+- /* shutdown any bulk reads that might be going on */
+- if (serial->num_bulk_out)
++ /* shutdown any bulk transfers that might be going on */
++ if (port->bulk_out_size)
+ usb_kill_urb(port->write_urb);
+- if (serial->num_bulk_in)
++ if (port->bulk_in_size)
+ usb_kill_urb(port->read_urb);
+ }
+ }
+@@ -333,15 +333,15 @@ int usb_serial_generic_write(struct tty_
+
+ dbg("%s - port %d", __func__, port->number);
+
++ /* only do something if we have a bulk out endpoint */
++ if (!port->bulk_out_size)
++ return -ENODEV;
++
+ if (count == 0) {
+ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
+ }
+
+- /* only do something if we have a bulk out endpoint */
+- if (!serial->num_bulk_out)
+- return 0;
+-
+ if (serial->type->max_in_flight_urbs)
+ return usb_serial_multi_urb_write(tty, port,
+ buf, count);
+@@ -364,14 +364,19 @@ int usb_serial_generic_write_room(struct
+ int room = 0;
+
+ dbg("%s - port %d", __func__, port->number);
++
++ if (!port->bulk_out_size)
++ return 0;
++
+ spin_lock_irqsave(&port->lock, flags);
+ if (serial->type->max_in_flight_urbs) {
+ if (port->urbs_in_flight < serial->type->max_in_flight_urbs)
+ room = port->bulk_out_size *
+ (serial->type->max_in_flight_urbs -
+ port->urbs_in_flight);
+- } else if (serial->num_bulk_out)
++ } else {
+ room = kfifo_avail(&port->write_fifo);
++ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ dbg("%s - returns %d", __func__, room);
+@@ -382,15 +387,18 @@ int usb_serial_generic_chars_in_buffer(s
+ {
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+- int chars = 0;
+ unsigned long flags;
++ int chars;
+
+ dbg("%s - port %d", __func__, port->number);
+
++ if (!port->bulk_out_size)
++ return 0;
++
+ spin_lock_irqsave(&port->lock, flags);
+ if (serial->type->max_in_flight_urbs)
+ chars = port->tx_bytes_flight;
+- else if (serial->num_bulk_out)
++ else
+ chars = kfifo_len(&port->write_fifo);
+ spin_unlock_irqrestore(&port->lock, flags);
+
diff --git a/usb.current/usb-unusual_devs.h-fix-capacity-for-sl11r-ide-2.6c.patch b/usb.current/usb-unusual_devs.h-fix-capacity-for-sl11r-ide-2.6c.patch
new file mode 100644
index 00000000000000..9578f96afd8e29
--- /dev/null
+++ b/usb.current/usb-unusual_devs.h-fix-capacity-for-sl11r-ide-2.6c.patch
@@ -0,0 +1,47 @@
+From linux@rainbow-software.org Mon Mar 15 13:17:08 2010
+From: Ondrej Zary <linux@rainbow-software.org>
+Date: Sat, 27 Feb 2010 22:56:28 +0100
+Subject: USB: unusual_devs.h: Fix capacity for SL11R-IDE 2.6c
+To: Phil Dibowitz <phil@ipom.com>
+Cc: stern@rowland.harvard.edu, linux-usb@vger.kernel.org, usb-storage@lists.one-eyed-alien.net
+Message-ID: <201002272256.31961.linux@rainbow-software.org>
+Content-Disposition: inline
+
+
+SL11R-IDE 2.6c (at least) reports wrong capacity (one sector more).
+Reading that last sector causes the device not to work anymore (and looks
+like HAL or something does that automatically after plugging in):
+sd 5:0:0:0: [sdc] Device not ready
+sd 5:0:0:0: [sdc] Result: hostbyte=0x00 driverbyte=0x08
+sd 5:0:0:0: [sdc] Sense Key : 0x2 [current]
+sd 5:0:0:0: [sdc] ASC=0x0 ASCQ=0x0
+sd 5:0:0:0: [sdc] CDB: cdb[0]=0x28: 28 00 04 a8 b5 70 00 00 01 00
+
+Add unusual_devs entry to fix the capacity.
+
+Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
+Signed-off-by: Phil Dibowitz <phil@ipom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/storage/unusual_devs.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -374,6 +374,15 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY),
+
++/* Reported by Ondrej Zary <linux@rainbow-software.org>
++ * The device reports one sector more and breaks when that sector is accessed
++ */
++UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c,
++ "ScanLogic",
++ "SL11R-IDE",
++ US_SC_DEVICE, US_PR_DEVICE, NULL,
++ US_FL_FIX_CAPACITY),
++
+ /* Reported by Kriston Fincher <kriston@airmail.net>
+ * Patch submitted by Sean Millichamp <sean@bruenor.org>
+ * This is to support the Panasonic PalmCam PV-SD4090