aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2007-10-24 14:36:03 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-24 14:36:03 -0700
commit4dfe9e6bdbdf5a69ed41c58411350bcbdbaf4d03 (patch)
treeebede9ac7baba3a8a329fe683b358f127e8154ab /usb
parent344fceebd77ff2e341f36f9821da096adcc3840f (diff)
downloadpatches-4dfe9e6bdbdf5a69ed41c58411350bcbdbaf4d03.tar.gz
usb patches and pci-bridge update from Kay
Also, build fix for 2.6.24-rc1 and my .config
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-autosuspend-for-cdc-acm.patch201
-rw-r--r--usb/usb-fix-interface-sysfs-file-creation-bug.patch43
-rw-r--r--usb/usb-fix-locking-in-idmouse.patch166
-rw-r--r--usb/usb-fix-read-vs.-disconnect-race-in-cytherm-driver.patch41
-rw-r--r--usb/usb-remove-unnecessary-zeroing-from-ub.patch93
-rw-r--r--usb/usb-serial-pl2303-support-for-io-data-device-rsaq5.patch40
-rw-r--r--usb/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch46
7 files changed, 630 insertions, 0 deletions
diff --git a/usb/usb-autosuspend-for-cdc-acm.patch b/usb/usb-autosuspend-for-cdc-acm.patch
new file mode 100644
index 00000000000000..4ee2f244fc9199
--- /dev/null
+++ b/usb/usb-autosuspend-for-cdc-acm.patch
@@ -0,0 +1,201 @@
+From oliver@neukum.org Wed Oct 24 14:29:56 2007
+From: Oliver Neukum <oliver@neukum.org>
+Date: Fri, 12 Oct 2007 17:24:28 +0200
+Subject: USB: autosuspend for cdc-acm
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, linux-usb-devel@lists.sourceforge.net
+Message-ID: <200710121724.29251.oliver@neukum.org>
+Content-Disposition: inline
+
+
+Here we go. This patch implements suspend/resume and autosuspend
+for the CDC ACM driver.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/class/cdc-acm.c | 92 ++++++++++++++++++++++++++++++++++++--------
+ drivers/usb/class/cdc-acm.h | 2
+ 2 files changed, 79 insertions(+), 15 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -496,10 +496,19 @@ static int acm_tty_open(struct tty_struc
+ otherwise it is scheduled, and with high data rates data can get lost. */
+ tty->low_latency = 1;
+
++ if (usb_autopm_get_interface(acm->control)) {
++ mutex_unlock(&open_mutex);
++ return -EIO;
++ }
++
++ mutex_lock(&acm->mutex);
++ mutex_unlock(&open_mutex);
+ if (acm->used++) {
++ usb_autopm_put_interface(acm->control);
+ goto done;
+ }
+
++
+ acm->ctrlurb->dev = acm->dev;
+ if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
+ dbg("usb_submit_urb(ctrl irq) failed");
+@@ -526,14 +535,15 @@ static int acm_tty_open(struct tty_struc
+
+ done:
+ err_out:
+- mutex_unlock(&open_mutex);
++ mutex_unlock(&acm->mutex);
+ return rv;
+
+ full_bailout:
+ usb_kill_urb(acm->ctrlurb);
+ bail_out:
++ usb_autopm_put_interface(acm->control);
+ acm->used--;
+- mutex_unlock(&open_mutex);
++ mutex_unlock(&acm->mutex);
+ return -EIO;
+ }
+
+@@ -570,6 +580,7 @@ static void acm_tty_close(struct tty_str
+ usb_kill_urb(acm->writeurb);
+ for (i = 0; i < nr; i++)
+ usb_kill_urb(acm->ru[i].urb);
++ usb_autopm_put_interface(acm->control);
+ } else
+ acm_tty_unregister(acm);
+ }
+@@ -980,6 +991,7 @@ skip_normal_probe:
+ spin_lock_init(&acm->throttle_lock);
+ spin_lock_init(&acm->write_lock);
+ spin_lock_init(&acm->read_lock);
++ mutex_init(&acm->mutex);
+ acm->write_ready = 1;
+ acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
+
+@@ -1096,6 +1108,25 @@ alloc_fail:
+ return -ENOMEM;
+ }
+
++static void stop_data_traffic(struct acm *acm)
++{
++ int i;
++
++ tasklet_disable(&acm->urb_task);
++
++ usb_kill_urb(acm->ctrlurb);
++ usb_kill_urb(acm->writeurb);
++ for (i = 0; i < acm->rx_buflimit; i++)
++ usb_kill_urb(acm->ru[i].urb);
++
++ INIT_LIST_HEAD(&acm->filled_read_bufs);
++ INIT_LIST_HEAD(&acm->spare_read_bufs);
++
++ tasklet_enable(&acm->urb_task);
++
++ cancel_work_sync(&acm->work);
++}
++
+ static void acm_disconnect(struct usb_interface *intf)
+ {
+ struct acm *acm = usb_get_intfdata(intf);
+@@ -1123,19 +1154,7 @@ static void acm_disconnect(struct usb_in
+ usb_set_intfdata(acm->control, NULL);
+ usb_set_intfdata(acm->data, NULL);
+
+- tasklet_disable(&acm->urb_task);
+-
+- usb_kill_urb(acm->ctrlurb);
+- usb_kill_urb(acm->writeurb);
+- for (i = 0; i < acm->rx_buflimit; i++)
+- usb_kill_urb(acm->ru[i].urb);
+-
+- INIT_LIST_HEAD(&acm->filled_read_bufs);
+- INIT_LIST_HEAD(&acm->spare_read_bufs);
+-
+- tasklet_enable(&acm->urb_task);
+-
+- flush_scheduled_work(); /* wait for acm_softint */
++ stop_data_traffic(acm);
+
+ acm_write_buffers_free(acm);
+ usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+@@ -1156,6 +1175,46 @@ static void acm_disconnect(struct usb_in
+ tty_hangup(acm->tty);
+ }
+
++static int acm_suspend(struct usb_interface *intf, pm_message_t message)
++{
++ struct acm *acm = usb_get_intfdata(intf);
++
++ if (acm->susp_count++)
++ return 0;
++ /*
++ we treat opened interfaces differently,
++ we must guard against open
++ */
++ mutex_lock(&acm->mutex);
++
++ if (acm->used)
++ stop_data_traffic(acm);
++
++ mutex_unlock(&acm->mutex);
++ return 0;
++}
++
++static int acm_resume(struct usb_interface *intf)
++{
++ struct acm *acm = usb_get_intfdata(intf);
++ int rv = 0;
++
++ if (--acm->susp_count)
++ return 0;
++
++ mutex_lock(&acm->mutex);
++ if (acm->used) {
++ rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
++ if (rv < 0)
++ goto err_out;
++
++ tasklet_schedule(&acm->urb_task);
++ }
++
++err_out:
++ mutex_unlock(&acm->mutex);
++ return rv;
++}
+ /*
+ * USB driver structure.
+ */
+@@ -1208,7 +1267,10 @@ static struct usb_driver acm_driver = {
+ .name = "cdc_acm",
+ .probe = acm_probe,
+ .disconnect = acm_disconnect,
++ .suspend = acm_suspend,
++ .resume = acm_resume,
+ .id_table = acm_ids,
++ .supports_autosuspend = 1,
+ };
+
+ /*
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -107,6 +107,7 @@ struct acm {
+ int write_used; /* number of non-empty write buffers */
+ int write_ready; /* write urb is not running */
+ spinlock_t write_lock;
++ struct mutex mutex;
+ struct usb_cdc_line_coding line; /* bits, stop, parity */
+ struct work_struct work; /* work queue entry for line discipline waking up */
+ struct tasklet_struct urb_task; /* rx processing */
+@@ -120,6 +121,7 @@ struct acm {
+ unsigned char throttle; /* throttled by tty layer */
+ unsigned char clocal; /* termios CLOCAL */
+ unsigned int ctrl_caps; /* control capabilities from the class specific header */
++ unsigned int susp_count; /* number of suspended interfaces */
+ };
+
+ #define CDC_DATA_INTERFACE_TYPE 0x0a
diff --git a/usb/usb-fix-interface-sysfs-file-creation-bug.patch b/usb/usb-fix-interface-sysfs-file-creation-bug.patch
new file mode 100644
index 00000000000000..802544caa904ec
--- /dev/null
+++ b/usb/usb-fix-interface-sysfs-file-creation-bug.patch
@@ -0,0 +1,43 @@
+From stern@rowland.harvard.edu Wed Oct 24 14:21:21 2007
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 19 Oct 2007 09:51:58 -0400 (EDT)
+Subject: USB: fix interface sysfs file-creation bug
+To: Greg KH <greg@kroah.com>
+Cc: USB development list <linux-usb-devel@lists.sourceforge.net>
+Message-ID: <Pine.LNX.4.44L0.0710190950520.3873-100000@iolanthe.rowland.org>
+
+
+This patch (as1005) fixes a rather subtle problem. When
+usb_set_configuration() registers the interfaces and their files in
+sysfs, it doesn't expect those files to exist already. But when an
+interface is registered, its driver may call usb_set_interface() and
+thereby cause the sysfs files to be created. The result is an error
+when usb_set_configuration() goes on to create those same files again.
+
+The (not-so-great) solution is to have usb_set_configuration() remove
+any existing files before creating them.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/message.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1641,7 +1641,13 @@ free_interfaces:
+ intf->dev.bus_id, ret);
+ continue;
+ }
+- usb_create_sysfs_intf_files (intf);
++
++ /* The driver's probe method can call usb_set_interface(),
++ * which would mean the interface's sysfs files are already
++ * created. Just in case, we'll remove them first.
++ */
++ usb_remove_sysfs_intf_files(intf);
++ usb_create_sysfs_intf_files(intf);
+ }
+
+ usb_autosuspend_device(dev);
diff --git a/usb/usb-fix-locking-in-idmouse.patch b/usb/usb-fix-locking-in-idmouse.patch
new file mode 100644
index 00000000000000..fcb27c8deb8a0f
--- /dev/null
+++ b/usb/usb-fix-locking-in-idmouse.patch
@@ -0,0 +1,166 @@
+From oliver@neukum.org Wed Oct 24 14:23:59 2007
+From: Oliver Neukum <oliver@neukum.org>
+Date: Tue, 23 Oct 2007 14:23:13 +0200
+Subject: USB: fix locking in idmouse
+To: echtler@fs.tum.de, aderesch@fs.tum.de, linux-usb-devel@lists.sourceforge.net, greg@kroah.com, Pete Zaitcev <zaitcev@redhat.com>
+Message-ID: <200710231423.14209.oliver@neukum.org>
+Content-Disposition: inline
+
+
+Pete caused me to lock at buggy drivers in this respect. The idmouse has
+a race between open and disconnect. This patch
+
+- solves the open/disconnect race
+- switches locking to mutexes
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/misc/idmouse.c | 45 ++++++++++++++++++++++++++++-----------------
+ 1 file changed, 28 insertions(+), 17 deletions(-)
+
+--- a/drivers/usb/misc/idmouse.c
++++ b/drivers/usb/misc/idmouse.c
+@@ -66,6 +66,7 @@ static struct usb_device_id idmouse_tabl
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000)
+
+ MODULE_DEVICE_TABLE(usb, idmouse_table);
++static DEFINE_MUTEX(open_disc_mutex);
+
+ /* structure to hold all of our device specific stuff */
+ struct usb_idmouse {
+@@ -80,7 +81,7 @@ struct usb_idmouse {
+
+ int open; /* if the port is open or not */
+ int present; /* if the device is not disconnected */
+- struct semaphore sem; /* locks this structure */
++ struct mutex lock; /* locks this structure */
+
+ };
+
+@@ -213,13 +214,17 @@ static int idmouse_open(struct inode *in
+ if (!interface)
+ return -ENODEV;
+
++ mutex_lock(&open_disc_mutex);
+ /* get the device information block from the interface */
+ dev = usb_get_intfdata(interface);
+- if (!dev)
++ if (!dev) {
++ mutex_unlock(&open_disc_mutex);
+ return -ENODEV;
++ }
+
+ /* lock this device */
+- down(&dev->sem);
++ mutex_lock(&dev->lock);
++ mutex_unlock(&open_disc_mutex);
+
+ /* check if already open */
+ if (dev->open) {
+@@ -245,7 +250,7 @@ static int idmouse_open(struct inode *in
+ error:
+
+ /* unlock this device */
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
+ return result;
+ }
+
+@@ -258,12 +263,14 @@ static int idmouse_release(struct inode
+ if (dev == NULL)
+ return -ENODEV;
+
++ mutex_lock(&open_disc_mutex);
+ /* lock our device */
+- down(&dev->sem);
++ mutex_lock(&dev->lock);
+
+ /* are we really open? */
+ if (dev->open <= 0) {
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
++ mutex_unlock(&open_disc_mutex);
+ return -ENODEV;
+ }
+
+@@ -271,10 +278,12 @@ static int idmouse_release(struct inode
+
+ if (!dev->present) {
+ /* the device was unplugged before the file was released */
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
++ mutex_unlock(&open_disc_mutex);
+ idmouse_delete(dev);
+ } else {
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
++ mutex_unlock(&open_disc_mutex);
+ }
+ return 0;
+ }
+@@ -286,18 +295,18 @@ static ssize_t idmouse_read(struct file
+ int result;
+
+ /* lock this object */
+- down(&dev->sem);
++ mutex_lock(&dev->lock);
+
+ /* verify that the device wasn't unplugged */
+ if (!dev->present) {
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
+ return -ENODEV;
+ }
+
+ result = simple_read_from_buffer(buffer, count, ppos,
+ dev->bulk_in_buffer, IMGSIZE);
+ /* unlock the device */
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
+ return result;
+ }
+
+@@ -320,7 +329,7 @@ static int idmouse_probe(struct usb_inte
+ if (dev == NULL)
+ return -ENOMEM;
+
+- init_MUTEX(&dev->sem);
++ mutex_init(&dev->lock);
+ dev->udev = udev;
+ dev->interface = interface;
+
+@@ -372,24 +381,26 @@ static void idmouse_disconnect(struct us
+
+ /* get device structure */
+ dev = usb_get_intfdata(interface);
+- usb_set_intfdata(interface, NULL);
+
+ /* give back our minor */
+ usb_deregister_dev(interface, &idmouse_class);
+
+- /* lock it */
+- down(&dev->sem);
++ mutex_lock(&open_disc_mutex);
++ usb_set_intfdata(interface, NULL);
++ /* lock the device */
++ mutex_lock(&dev->lock);
++ mutex_unlock(&open_disc_mutex);
+
+ /* prevent device read, write and ioctl */
+ dev->present = 0;
+
+ /* if the device is opened, idmouse_release will clean this up */
+ if (!dev->open) {
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
+ idmouse_delete(dev);
+ } else {
+ /* unlock */
+- up(&dev->sem);
++ mutex_unlock(&dev->lock);
+ }
+
+ info("%s disconnected", DRIVER_DESC);
diff --git a/usb/usb-fix-read-vs.-disconnect-race-in-cytherm-driver.patch b/usb/usb-fix-read-vs.-disconnect-race-in-cytherm-driver.patch
new file mode 100644
index 00000000000000..19ff2411402351
--- /dev/null
+++ b/usb/usb-fix-read-vs.-disconnect-race-in-cytherm-driver.patch
@@ -0,0 +1,41 @@
+From oliver@neukum.org Wed Oct 24 14:24:18 2007
+From: Oliver Neukum <oliver@neukum.org>
+Date: Tue, 23 Oct 2007 12:26:41 +0200
+Subject: USB: fix read vs. disconnect race in cytherm driver
+To: erik@rigtorp.com, greg@kroah.com, linux-usb-devel@lists.sourceforge.net
+Message-ID: <200710231226.41769.oliver@neukum.org>
+Content-Disposition: inline
+
+
+the disconnect method of this driver set intfdata to NULL before
+removing attribute files. The attributes' read methods will happily
+follow the NULL pointer. Here's the correct ordering.
+
+Signed-off-by : Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/misc/cytherm.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/misc/cytherm.c
++++ b/drivers/usb/misc/cytherm.c
+@@ -399,7 +399,6 @@ static void cytherm_disconnect(struct us
+ struct usb_cytherm *dev;
+
+ dev = usb_get_intfdata (interface);
+- usb_set_intfdata (interface, NULL);
+
+ device_remove_file(&interface->dev, &dev_attr_brightness);
+ device_remove_file(&interface->dev, &dev_attr_temp);
+@@ -407,6 +406,9 @@ static void cytherm_disconnect(struct us
+ device_remove_file(&interface->dev, &dev_attr_port0);
+ device_remove_file(&interface->dev, &dev_attr_port1);
+
++ /* first remove the files, then NULL the pointer */
++ usb_set_intfdata (interface, NULL);
++
+ usb_put_dev(dev->udev);
+
+ kfree(dev);
diff --git a/usb/usb-remove-unnecessary-zeroing-from-ub.patch b/usb/usb-remove-unnecessary-zeroing-from-ub.patch
new file mode 100644
index 00000000000000..a72793abf69fa7
--- /dev/null
+++ b/usb/usb-remove-unnecessary-zeroing-from-ub.patch
@@ -0,0 +1,93 @@
+From zaitcev@redhat.com Wed Oct 24 14:22:09 2007
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Tue, 23 Oct 2007 18:57:25 -0700
+Subject: USB: Remove unnecessary zeroing from ub
+To: greg@kroah.com
+Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net
+Message-ID: <20071023185725.9892f3e2.zaitcev@redhat.com>
+
+
+These zeroings were taken from usb-storage long time ago. I examined
+the submission paths and usb_fill_bulk_urb and found them unnecessary.
+
+Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/block/ub.c | 23 -----------------------
+ 1 file changed, 23 deletions(-)
+
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -922,11 +922,6 @@ static int ub_scsi_cmd_start(struct ub_d
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
+ bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
+
+- /* Fill what we shouldn't be filling, because usb-storage did so. */
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+-
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ /* XXX Clear stalls */
+ ub_complete(&sc->work_done);
+@@ -1313,9 +1308,6 @@ static void ub_data_start(struct ub_dev
+ sc->last_pipe = pipe;
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
+ sg->length, ub_urb_complete, sc);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ /* XXX Clear stalls */
+@@ -1356,9 +1348,6 @@ static int __ub_state_stat(struct ub_dev
+ sc->last_pipe = sc->recv_bulk_pipe;
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
+ &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ /* XXX Clear stalls */
+@@ -1473,9 +1462,6 @@ static int ub_submit_clear_stall(struct
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ ub_complete(&sc->work_done);
+@@ -1954,9 +1940,6 @@ static int ub_sync_reset(struct ub_dev *
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ printk(KERN_WARNING
+@@ -2008,9 +1991,6 @@ static int ub_sync_getmaxlun(struct ub_d
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
+ (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
+ goto err_submit;
+@@ -2078,9 +2058,6 @@ static int ub_probe_clear_stall(struct u
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+- sc->work_urb.actual_length = 0;
+- sc->work_urb.error_count = 0;
+- sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ printk(KERN_WARNING
diff --git a/usb/usb-serial-pl2303-support-for-io-data-device-rsaq5.patch b/usb/usb-serial-pl2303-support-for-io-data-device-rsaq5.patch
new file mode 100644
index 00000000000000..ac8c8340a5996d
--- /dev/null
+++ b/usb/usb-serial-pl2303-support-for-io-data-device-rsaq5.patch
@@ -0,0 +1,40 @@
+From mokuno@sm.sony.co.jp Wed Oct 24 14:24:40 2007
+From: Masakazu Mokuno <mokuno@sm.sony.co.jp>
+Date: Tue, 23 Oct 2007 13:51:57 +0900
+Subject: usb: serial/pl2303: support for IO Data Device RSAQ5
+To: Greg KH <greg@kroah.com>
+Cc: linux-usb-devel@lists.sourceforge.net
+Message-ID: <20071023133459.E0CE.MOKUNO@sm.sony.co.jp>
+
+
+This patch adds support for the IO Data Device USB-RSAQ5, PL2303 based
+USB-serial converter, to pl2303 driver
+
+Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/pl2303.c | 1 +
+ drivers/usb/serial/pl2303.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -56,6 +56,7 @@ static struct usb_device_id id_table []
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
++ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
+ { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+ { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
+--- a/drivers/usb/serial/pl2303.h
++++ b/drivers/usb/serial/pl2303.h
+@@ -20,6 +20,7 @@
+
+ #define IODATA_VENDOR_ID 0x04bb
+ #define IODATA_PRODUCT_ID 0x0a03
++#define IODATA_PRODUCT_ID_RSAQ5 0x0a0e
+
+ #define ELCOM_VENDOR_ID 0x056e
+ #define ELCOM_PRODUCT_ID 0x5003
diff --git a/usb/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch b/usb/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch
new file mode 100644
index 00000000000000..39cc56f9ce9c41
--- /dev/null
+++ b/usb/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch
@@ -0,0 +1,46 @@
+From jikos@jikos.cz Wed Oct 24 14:28:04 2007
+From: Jiri Kosina <jikos@jikos.cz>
+Date: Sat, 20 Oct 2007 00:05:19 +0200 (CEST)
+Subject: USB: usbserial - fix potential deadlock between write() and IRQ
+To: Larry Finger <larry.finger@lwfinger.net>
+Cc: LKML <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@suse.de>, linux-usb-devel@lists.sourceforge.net
+Message-ID: <Pine.LNX.4.64.0710200001520.18815@twin.jikos.cz>
+
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+USB: usbserial - fix potential deadlock between write() and IRQ
+
+usb_serial_generic_write() doesn't disable interrupts when taking port->lock,
+and could therefore deadlock with usb_serial_generic_read_bulk_callback()
+being called from interrupt, taking the same lock. Fix it.
+
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Acked-by: Larry Finger <larry.finger@lwfinger.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/generic.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -208,14 +208,15 @@ int usb_serial_generic_write(struct usb_
+
+ /* only do something if we have a bulk out endpoint */
+ if (serial->num_bulk_out) {
+- spin_lock_bh(&port->lock);
++ unsigned long flags;
++ spin_lock_irqsave(&port->lock, flags);
+ if (port->write_urb_busy) {
+- spin_unlock_bh(&port->lock);
++ spin_unlock_irqrestore(&port->lock, flags);
+ dbg("%s - already writing", __FUNCTION__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+- spin_unlock_bh(&port->lock);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+