aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-10-27 10:54:41 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-10-27 10:54:41 -0700
commit607008879414ffa8d5f424a3646cca2644119c3b (patch)
tree32c49c67c62c88b9559f644f418b1c585122f2d7
parentd93ada0e086cc8b5de957b5dfaeb1247489f1717 (diff)
downloadpatches-607008879414ffa8d5f424a3646cca2644119c3b.tar.gz
more patches
-rw-r--r--series22
-rw-r--r--staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch157
-rw-r--r--staging/staging-comedi-adl_pci8164-coding-style-fixes.patch122
-rw-r--r--staging/staging-comedi-multiq3-add-kern_.patch55
-rw-r--r--staging/staging-comedi-multiq3-remove-warning-on-braces.patch61
-rw-r--r--staging/staging-comedi-pcl726-fix-coding-style-issues.patch128
-rw-r--r--staging/staging-vt6655-correct-unsigned-bound-issue.patch41
-rw-r--r--tty/opticon-fix-resume-logic.patch32
-rw-r--r--tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch72
-rw-r--r--tty/serial-cascade-needless-conditionals.patch55
-rw-r--r--tty/serial-fix-null-pointer-dereference.patch71
-rw-r--r--tty/tty_port-add-tty_port_open-helper.patch174
-rw-r--r--tty/tty_port-coding-style-cleaning-pass.patch98
-rw-r--r--tty/usb_serial-kill-port-mutex.patch68
-rw-r--r--tty/usb_serial-use-the-shutdown-operation.patch124
-rw-r--r--usb.current/usb-option-tlaytech-tue800-support.patch40
-rw-r--r--usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch57
-rw-r--r--usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch82
-rw-r--r--usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch797
-rw-r--r--usb/usb-improved-error-handling-in-usb_port_suspend.patch48
-rw-r--r--usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch217
-rw-r--r--usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch154
22 files changed, 2674 insertions, 1 deletions
diff --git a/series b/series
index aba0b93445ce9c..97a4eae8836a2d 100644
--- a/series
+++ b/series
@@ -21,6 +21,9 @@ driver-core.current/driver-core-allow-certain-drivers-prohibit-bind-unbind-via-s
# USB patches for 2.6.32
#################################
usb.current/usb-rndis_host-debug-info-clobbered-before-it-is-logged.patch
+usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch
+usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch
+usb.current/usb-option-tlaytech-tue800-support.patch
#################################
@@ -59,6 +62,14 @@ tty/tty-const-constify-remaining-tty_operations.patch
tty/tty-esp-remove-broken-driver.patch
tty/tty-istallion-kill-off-the-bkl-ioctl.patch
tty/tty-stallion-kill-bkl-ioctl.patch
+tty/tty_port-add-tty_port_open-helper.patch
+tty/tty_port-coding-style-cleaning-pass.patch
+tty/usb_serial-use-the-shutdown-operation.patch
+tty/usb_serial-kill-port-mutex.patch
+tty/opticon-fix-resume-logic.patch
+tty/serial-fix-null-pointer-dereference.patch
+tty/serial-cascade-needless-conditionals.patch
+tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch
#################################
# USB stuff (after 2.6.32 is out)
@@ -81,6 +92,10 @@ usb/usb-modifications-for-at91sam9g10.patch
usb/usb-usbtmc-minor-formatting-cleanups.patch
usb/usb-whci-hcd-decode-more-qhead-fields-in-the-debug-files.patch
usb/usb-wusb-add-wusb_phy_rate-sysfs-file-to-host-controllers.patch
+usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch
+usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch
+usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch
+usb/usb-improved-error-handling-in-usb_port_suspend.patch
#################################
# Staging stuff
@@ -134,6 +149,11 @@ staging/staging-comedi-remove-check-for-have_compat_ioctl.patch
staging/staging-comedi-don-t-check-for-enoioctlcmd.patch
staging/staging-comedi-remove-__cplusplus-check.patch
staging/staging-comedi-remove-extern-macro-since-it-is-not-used.patch
+staging/staging-comedi-adl_pci8164-coding-style-fixes.patch
+staging/staging-comedi-multiq3-remove-warning-on-braces.patch
+staging/staging-comedi-multiq3-add-kern_.patch
+staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch
+staging/staging-comedi-pcl726-fix-coding-style-issues.patch
staging/staging-xvmalloc-memory-allocator.patch
staging/staging-virtual-block-device-driver.patch
@@ -212,6 +232,7 @@ staging/staging-netwave-move-driver-to-staging.patch
staging/staging-netwave-add-todo-file.patch
staging/staging-octeon-don-t-ignore-request_irq-return-code.patch
staging/staging-vt6656-use-lowercase-for-via-usb-vendor-id.patch
+staging/staging-vt6655-correct-unsigned-bound-issue.patch
staging/staging-remove-stlc45xx-driver.patch
# tty stuff still under work
@@ -223,4 +244,3 @@ staging/staging-remove-stlc45xx-driver.patch
#tty.work/serial-f81216-helper
-
diff --git a/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch b/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch
new file mode 100644
index 00000000000000..1d3c5721aebd7e
--- /dev/null
+++ b/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch
@@ -0,0 +1,157 @@
+From roel.kluin@gmail.com Tue Oct 27 10:37:41 2009
+From: Roel Kluin <roel.kluin@gmail.com>
+Date: Fri, 23 Oct 2009 12:26:25 +0200
+Subject: Staging: comedi: addi-data: Cleanup redundant tests on unsigned
+To: Greg Kroah-Hartman <gregkh@suse.de>, Bill Pemberton <wfp5p@virginia.edu>, devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org>
+Message-ID: <4AE184D1.4030006@gmail.com>
+
+
+The variables are unsigned so the test `>= 0' is always true,
+In these cases the other part of the test catch wrapped values.
+
+Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c | 3 +--
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c | 4 ++--
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c | 5 ++---
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c | 2 +-
+ drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c | 2 +-
+ 10 files changed, 12 insertions(+), 14 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -1386,8 +1386,7 @@ int i_APCI1710_ReadChronoValue(struct co
+ /* Test the timout parameter */
+ /*****************************/
+
+- if ((ui_TimeOut >= 0)
+- && (ui_TimeOut <= 65535UL)) {
++ if (ui_TimeOut <= 65535UL) {
+
+ for (;;) {
+ /*******************/
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -150,7 +150,7 @@ int i_APCI1032_Read1DigitalInput(struct
+ unsigned int ui_TmpValue = 0;
+ unsigned int ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+- if (ui_Channel >= 0 && ui_Channel <= 31) {
++ if (ui_Channel <= 31) {
+ ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+ /*
+ * since only 1 channel reqd to bring it to last bit it is rotated 8
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -968,7 +968,7 @@ int i_APCI1500_ReadMoreDigitalInput(stru
+
+ switch (data[0]) {
+ case 0:
+- if (ui_Channel >= 0 && ui_Channel <= 15) {
++ if (ui_Channel <= 15) {
+ ui_TmpValue =
+ (unsigned int) inw(devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_IP);
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -79,7 +79,7 @@ int i_APCI1516_Read1DigitalInput(struct
+ unsigned int ui_TmpValue = 0;
+ unsigned int ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+- if (ui_Channel >= 0 && ui_Channel <= 7) {
++ if (ui_Channel <= 7) {
+ ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+ /* since only 1 channel reqd to bring it to last bit it is rotated */
+ /* 8 +(chan - 1) times then ANDed with 1 for last bit. */
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -154,7 +154,7 @@ int i_APCI1564_Read1DigitalInput(struct
+ unsigned int ui_Channel;
+
+ ui_Channel = CR_CHAN(insn->chanspec);
+- if (ui_Channel >= 0 && ui_Channel <= 31) {
++ if (ui_Channel <= 31) {
+ ui_TmpValue =
+ (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+ /*
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -117,7 +117,7 @@ int i_APCI2016_WriteDigitalOutput(struct
+ unsigned int ui_NoOfChannel;
+ unsigned int ui_Temp, ui_Temp1;
+ ui_NoOfChannel = CR_CHAN(insn->chanspec);
+- if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
++ if (ui_NoOfChannel > 15) {
+ comedi_error(dev,
+ "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ return -EINVAL;
+@@ -272,7 +272,7 @@ int i_APCI2016_BitsDigitalOutput(struct
+ unsigned int ui_Temp;
+ unsigned int ui_NoOfChannel;
+ ui_NoOfChannel = CR_CHAN(insn->chanspec);
+- if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
++ if (ui_NoOfChannel > 15) {
+ comedi_error(dev,
+ "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ return -EINVAL;
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -79,7 +79,7 @@ int i_APCI2200_Read1DigitalInput(struct
+ unsigned int ui_TmpValue = 0;
+ unsigned int ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+- if (ui_Channel >= 0 && ui_Channel <= 7) {
++ if (ui_Channel <= 7) {
+ ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } /* if(ui_Channel >= 0 && ui_Channel <=7) */
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -2350,7 +2350,7 @@ int i_APCI3120_InsnReadDigitalInput(stru
+ ui_Chan = CR_CHAN(insn->chanspec); /* channel specified */
+
+ /* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */
+- if (ui_Chan >= 0 && ui_Chan <= 3) {
++ if (ui_Chan <= 3) {
+ ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ /*
+@@ -2539,8 +2539,7 @@ int i_APCI3120_InsnWriteDigitalOutput(st
+ "Not a valid Data !!! ,Data should be 1 or 0\n");
+ return -EINVAL;
+ }
+- if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1))
+- || (ui_NoOfChannel < 0)) {
++ if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) {
+ comedi_error(dev,
+ "This board doesn't have specified channel !!! \n");
+ return -EINVAL;
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -461,7 +461,7 @@ int i_APCI3200_GetChannelCalibrationValu
+ if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
+ /* if diff */
+
+- if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1))
++ if (ui_Channel_num <= 1)
+ i_DiffChannel = ui_Channel_num, i_Module = 0;
+ else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3))
+ i_DiffChannel = ui_Channel_num - 2, i_Module = 1;
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -148,7 +148,7 @@ int i_APCI3XXX_AnalogInputConfigOperatin
+ /* Test the convert time value */
+ /*******************************/
+
+- if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) {
++ if (dw_ReloadValue <= 65535) {
+ dw_TestReloadValue = dw_ReloadValue;
+
+ if (b_TimeBase == 1) {
diff --git a/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch b/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch
new file mode 100644
index 00000000000000..1316aa0b96cee5
--- /dev/null
+++ b/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch
@@ -0,0 +1,122 @@
+From bruno.braga@gmail.com Tue Oct 27 10:33:27 2009
+From: "BRAGA, Bruno" <bruno.braga@gmail.com>
+Date: Thu, 22 Oct 2009 11:55:36 +0900
+Subject: Staging: comedi: adl_pci8164 coding style fixes
+To: Greg KH <greg@kroah.com>
+Message-ID: <86ca47940910211955y4c6083eco32f8a7fe95fdecaf@mail.gmail.com>
+
+From: BRAGA, Bruno <bruno.braga@gmail.com>
+
+Corrected coding style:
+- excessive curly braces
+- printk without KERN_* logging
+- 80+ chars per line of code
+
+Signed-off-by: BRAGA, Bruno <bruno.braga@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/comedi/drivers/adl_pci8164.c | 37 +++++++++++++--------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -35,6 +35,7 @@ Configuration Options:
+ */
+
+ #include "../comedidev.h"
++#include <linux/kernel.h>
+ #include <linux/delay.h>
+ #include "comedi_fc.h"
+ #include "comedi_pci.h"
+@@ -128,8 +129,8 @@ static int adl_pci8164_attach(struct com
+ struct comedi_subdevice *s;
+ int bus, slot;
+
+- printk("comedi: attempt to attach...\n");
+- printk("comedi%d: adl_pci8164\n", dev->minor);
++ printk(KERN_INFO "comedi: attempt to attach...\n");
++ printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
+
+ dev->board_name = "pci8164";
+ bus = it->options[0];
+@@ -150,19 +151,18 @@ static int adl_pci8164_attach(struct com
+ if (bus || slot) {
+ /* requested particular bus/slot */
+ if (pcidev->bus->number != bus
+- || PCI_SLOT(pcidev->devfn) != slot) {
++ || PCI_SLOT(pcidev->devfn) != slot)
+ continue;
+- }
+ }
+ devpriv->pci_dev = pcidev;
+ if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
+- printk
+- ("comedi%d: Failed to enable PCI device and request regions\n",
+- dev->minor);
++ printk(KERN_ERR "comedi%d: Failed to enable "
++ "PCI device and request regions\n", dev->minor);
+ return -EIO;
+ }
+ dev->iobase = pci_resource_start(pcidev, 2);
+- printk("comedi: base addr %4lx\n", dev->iobase);
++ printk(KERN_DEBUG "comedi: base addr %4lx\n",
++ dev->iobase);
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_PROC;
+@@ -204,25 +204,24 @@ static int adl_pci8164_attach(struct com
+ s->insn_read = adl_pci8164_insn_read_buf1;
+ s->insn_write = adl_pci8164_insn_write_buf1;
+
+- printk("comedi: attached\n");
++ printk(KERN_INFO "comedi: attached\n");
+
+ return 1;
+ }
+ }
+
+- printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
+- dev->minor, bus, slot);
++ printk(KERN_ERR "comedi%d: no supported board found!"
++ "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
+ return -EIO;
+ }
+
+ static int adl_pci8164_detach(struct comedi_device *dev)
+ {
+- printk("comedi%d: pci8164: remove\n", dev->minor);
++ printk(KERN_INFO "comedi%d: pci8164: remove\n", dev->minor);
+
+ if (devpriv && devpriv->pci_dev) {
+- if (dev->iobase) {
++ if (dev->iobase)
+ comedi_pci_disable(devpriv->pci_dev);
+- }
+ pci_dev_put(devpriv->pci_dev);
+ }
+
+@@ -267,8 +266,9 @@ static void adl_pci8164_insn_read(struct
+ }
+
+ data[0] = inw(dev->iobase + axis_reg + offset);
+- printk("comedi: pci8164 %s read -> %04X:%04X on axis %s\n", action,
+- data[0], data[1], axisname);
++ printk(KERN_DEBUG "comedi: pci8164 %s read -> "
++ "%04X:%04X on axis %s\n",
++ action, data[0], data[1], axisname);
+ }
+
+ static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
+@@ -347,8 +347,9 @@ static void adl_pci8164_insn_out(struct
+
+ outw(data[0], dev->iobase + axis_reg + offset);
+
+- printk("comedi: pci8164 %s write -> %04X:%04X on axis %s\n", action,
+- data[0], data[1], axisname);
++ printk(KERN_DEBUG "comedi: pci8164 %s write -> "
++ "%04X:%04X on axis %s\n",
++ action, data[0], data[1], axisname);
+
+ }
+
diff --git a/staging/staging-comedi-multiq3-add-kern_.patch b/staging/staging-comedi-multiq3-add-kern_.patch
new file mode 100644
index 00000000000000..34d5b575bff232
--- /dev/null
+++ b/staging/staging-comedi-multiq3-add-kern_.patch
@@ -0,0 +1,55 @@
+From klaas.van.gend@mvista.com Tue Oct 27 10:34:48 2009
+From: Klaas van Gend <klaas.van.gend@mvista.com>
+Date: Thu, 22 Oct 2009 07:51:00 +0200
+Subject: staging: comedi: multiq3: add KERN_
+To: gregkh@suse.de
+Cc: Klaas van Gend <klaas.van.gend@mvista.com>
+Message-ID: <1256190660-14913-2-git-send-email-klaas.van.gend@mvista.com>
+
+
+Add KERN_ to printk statements to reduce the number of warnings
+shown by checkpatch.pl.
+
+Signed-off-by: Klaas van Gend <klaas.van.gend@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/comedi/drivers/multiq3.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -252,9 +252,9 @@ static int multiq3_attach(struct comedi_
+ struct comedi_subdevice *s;
+
+ iobase = it->options[0];
+- printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase);
++ printk(KERN_INFO "comedi%d: multiq3: 0x%04lx ", dev->minor, iobase);
+ if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) {
+- printk("comedi%d: I/O port conflict\n", dev->minor);
++ printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
+ return -EIO;
+ }
+
+@@ -262,9 +262,10 @@ static int multiq3_attach(struct comedi_
+
+ irq = it->options[1];
+ if (irq)
+- printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
++ printk(KERN_WARNING "comedi%d: irq = %u ignored\n",
++ dev->minor, irq);
+ else
+- printk("comedi%d: no irq\n", dev->minor);
++ printk(KERN_WARNING "comedi%d: no irq\n", dev->minor);
+ dev->board_name = "multiq3";
+ result = alloc_subdevices(dev, 5);
+ if (result < 0)
+@@ -328,7 +329,7 @@ static int multiq3_attach(struct comedi_
+
+ static int multiq3_detach(struct comedi_device *dev)
+ {
+- printk("comedi%d: multiq3: remove\n", dev->minor);
++ printk(KERN_INFO "comedi%d: multiq3: remove\n", dev->minor);
+
+ if (dev->iobase)
+ release_region(dev->iobase, MULTIQ3_SIZE);
diff --git a/staging/staging-comedi-multiq3-remove-warning-on-braces.patch b/staging/staging-comedi-multiq3-remove-warning-on-braces.patch
new file mode 100644
index 00000000000000..74d8f5318d73d9
--- /dev/null
+++ b/staging/staging-comedi-multiq3-remove-warning-on-braces.patch
@@ -0,0 +1,61 @@
+From klaas.van.gend@mvista.com Tue Oct 27 10:34:35 2009
+From: Klaas van Gend <klaas.van.gend@mvista.com>
+Date: Thu, 22 Oct 2009 07:50:59 +0200
+Subject: staging: comedi: multiq3: remove warning on braces
+To: gregkh@suse.de
+Cc: Klaas van Gend <klaas.van.gend@mvista.com>
+Message-ID: <1256190660-14913-1-git-send-email-klaas.van.gend@mvista.com>
+
+
+Remove braces in if statements to make the file exhibit less warnings
+when checked using checkpatch.pl.
+
+Signed-off-by: Klaas van Gend <klaas.van.gend@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/comedi/drivers/multiq3.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -144,9 +144,8 @@ static int multiq3_ao_insn_read(struct c
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+
+- for (i = 0; i < insn->n; i++) {
++ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_readback[chan];
+- }
+
+ return i;
+ }
+@@ -262,11 +261,10 @@ static int multiq3_attach(struct comedi_
+ dev->iobase = iobase;
+
+ irq = it->options[1];
+- if (irq) {
++ if (irq)
+ printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
+- } else {
++ else
+ printk("comedi%d: no irq\n", dev->minor);
+- }
+ dev->board_name = "multiq3";
+ result = alloc_subdevices(dev, 5);
+ if (result < 0)
+@@ -332,12 +330,10 @@ static int multiq3_detach(struct comedi_
+ {
+ printk("comedi%d: multiq3: remove\n", dev->minor);
+
+- if (dev->iobase) {
++ if (dev->iobase)
+ release_region(dev->iobase, MULTIQ3_SIZE);
+- }
+- if (dev->irq) {
++ if (dev->irq)
+ free_irq(dev->irq, dev);
+- }
+
+ return 0;
+ }
diff --git a/staging/staging-comedi-pcl726-fix-coding-style-issues.patch b/staging/staging-comedi-pcl726-fix-coding-style-issues.patch
new file mode 100644
index 00000000000000..e6fd1d1ab07f9e
--- /dev/null
+++ b/staging/staging-comedi-pcl726-fix-coding-style-issues.patch
@@ -0,0 +1,128 @@
+From kevyn.alexandre.pare@gmail.com Tue Oct 27 10:38:04 2009
+From: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com>
+Date: Fri, 23 Oct 2009 17:34:17 -0400
+Subject: Staging: comedi: pcl726: fix coding style issues
+To: greg@kroah.com
+Cc: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com>
+Message-ID: <1256333657-12832-1-git-send-email-kevyn.alexandre.pare@gmail.com>
+Status: RO
+X-Status: A
+Content-Length: 3541
+Lines: 115
+
+
+From: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com>
+
+Signed-off-by: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/comedi/drivers/pcl726.c | 41 +++++++++++++++-----------------
+ 1 file changed, 20 insertions(+), 21 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -39,27 +39,27 @@ Interrupts are not supported.
+ Options for PCL-726:
+ [0] - IO Base
+ [2]...[7] - D/A output range for channel 1-6:
+- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
+- 4: 4-20mA, 5: unknown (external reference)
++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
++ 4: 4-20mA, 5: unknown (external reference)
+
+ Options for PCL-727:
+ [0] - IO Base
+ [2]...[13] - D/A output range for channel 1-12:
+- 0: 0-5V, 1: 0-10V, 2: +/-5V,
+- 3: 4-20mA
++ 0: 0-5V, 1: 0-10V, 2: +/-5V,
++ 3: 4-20mA
+
+ Options for PCL-728 and ACL-6128:
+ [0] - IO Base
+ [2], [3] - D/A output range for channel 1 and 2:
+- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
+- 4: 4-20mA, 5: 0-20mA
++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
++ 4: 4-20mA, 5: 0-20mA
+
+ Options for ACL-6126:
+ [0] - IO Base
+ [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored)
+ [2]...[7] - D/A output range for channel 1-6:
+- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
+- 4: 4-20mA
++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
++ 4: 4-20mA
+ */
+
+ /*
+@@ -127,7 +127,8 @@ struct pcl726_board {
+ int di_lo;
+ int do_hi;
+ int do_lo;
+- const struct comedi_lrange *const *range_type_list; /* list of supported ranges */
++ const struct comedi_lrange *const *range_type_list;
++ /* list of supported ranges */
+ };
+
+ static const struct pcl726_board boardtypes[] = {
+@@ -204,9 +205,8 @@ static int pcl726_ao_insn_read(struct co
+ int chan = CR_CHAN(insn->chanspec);
+ int n;
+
+- for (n = 0; n < insn->n; n++) {
++ for (n = 0; n < insn->n; n++)
+ data[n] = devpriv->ao_readback[chan];
+- }
+ return n;
+ }
+
+@@ -256,10 +256,10 @@ static int pcl726_attach(struct comedi_d
+
+ iobase = it->options[0];
+ iorange = this_board->io_range;
+- printk("comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor,
++ printk(KERN_WARNING "comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor,
+ this_board->name, iobase);
+ if (!request_region(iobase, iorange, "pcl726")) {
+- printk("I/O port conflict\n");
++ printk(KERN_WARNING "I/O port conflict\n");
+ return -EIO;
+ }
+
+@@ -283,16 +283,16 @@ static int pcl726_attach(struct comedi_d
+ devpriv->first_chan = 2;
+ if (irq) { /* we want to use IRQ */
+ if (((1 << irq) & boardtypes[board].IRQbits) == 0) {
+- printk
+- (", IRQ %d is out of allowed range, DISABLING IT",
+- irq);
++ printk(KERN_WARNING
++ ", IRQ %d is out of allowed range,"
++ " DISABLING IT", irq);
+ irq = 0; /* Bad IRQ */
+ } else {
+ if (request_irq(irq, interrupt_pcl818, 0,
+ "pcl726", dev)) {
+- printk
+- (", unable to allocate IRQ %d, DISABLING IT",
+- irq);
++ printk(KERN_WARNING
++ ", unable to allocate IRQ %d,"
++ " DISABLING IT", irq);
+ irq = 0; /* Can't use IRQ */
+ } else {
+ printk(", irq=%d", irq);
+@@ -372,9 +372,8 @@ static int pcl726_detach(struct comedi_d
+ /* printk("comedi%d: pcl726: remove\n",dev->minor); */
+
+ #ifdef ACL6126_IRQ
+- if (dev->irq) {
++ if (dev->irq)
+ free_irq(dev->irq, dev);
+- }
+ #endif
+
+ if (dev->iobase)
diff --git a/staging/staging-vt6655-correct-unsigned-bound-issue.patch b/staging/staging-vt6655-correct-unsigned-bound-issue.patch
new file mode 100644
index 00000000000000..4bc6f30dd04793
--- /dev/null
+++ b/staging/staging-vt6655-correct-unsigned-bound-issue.patch
@@ -0,0 +1,41 @@
+From roel.kluin@gmail.com Tue Oct 27 10:22:28 2009
+From: Roel Kluin <roel.kluin@gmail.com>
+Date: Fri, 16 Oct 2009 20:17:57 +0200
+Subject: Staging: vt6655: Correct unsigned bound issue
+To: Roel Kluin <roel.kluin@gmail.com>
+Cc: devel@driverdev.osuosl.org, Andrew Morton <akpm@linux-foundation.org>, Greg Kroah-Hartman <gregkh@suse.de>
+Message-ID: <4AD8B8D5.40906@gmail.com>
+
+
+uNodeIndex is unsigned, check whether it is within bounds instead.
+
+Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/staging/vt6655/wroute.c | 2 +-
+ drivers/staging/vt6656/rxtx.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vt6655/wroute.c
++++ b/drivers/staging/vt6655/wroute.c
+@@ -113,7 +113,7 @@ BOOL ROUTEbRelay (PSDevice pDevice, PBYT
+ }
+
+ if (pDevice->bEnableHostWEP) {
+- if (uNodeIndex >= 0) {
++ if (uNodeIndex < MAX_NODE_NUM + 1) {
+ pTransmitKey = &STempKey;
+ pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+ pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
+--- a/drivers/staging/vt6656/rxtx.c
++++ b/drivers/staging/vt6656/rxtx.c
+@@ -3153,7 +3153,7 @@ bRelayPacketSend (
+ }
+
+ if (pDevice->bEnableHostWEP) {
+- if (uNodeIndex >= 0) {
++ if (uNodeIndex < MAX_NODE_NUM + 1) {
+ pTransmitKey = &STempKey;
+ pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
+ pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
diff --git a/tty/opticon-fix-resume-logic.patch b/tty/opticon-fix-resume-logic.patch
new file mode 100644
index 00000000000000..3335b23dd16710
--- /dev/null
+++ b/tty/opticon-fix-resume-logic.patch
@@ -0,0 +1,32 @@
+From alan@linux.intel.com Tue Oct 27 10:08:01 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:57 +0100
+Subject: [PATCH 5/5] opticon: Fix resume logic
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150651.9431.16939.stgit@localhost.localdomain>
+
+
+Opticon now takes the right mutex to check the port status but the status
+check is done wrongly for the modern serial code, so fix it.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/opticon.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -502,7 +502,8 @@ static int opticon_resume(struct usb_int
+ int result;
+
+ mutex_lock(&port->port.mutex);
+- if (port->port.count)
++ /* This is protected by the port mutex against close/open */
++ if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
+ else
+ result = 0;
diff --git a/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch
new file mode 100644
index 00000000000000..e67d804738ce1d
--- /dev/null
+++ b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch
@@ -0,0 +1,72 @@
+From andre.goddard@gmail.com Tue Oct 27 10:44:02 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 12:01:34 -0200
+Subject: serial, 8250: calculate irqflags bitmask before loop
+To: alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, ddaney@caviumnetworks.com, tpaoletti@caviumnetworks.com, gregkh@suse.de
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250701r58d25082y12ea482f6c1b2ea4@mail.gmail.com>
+
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -2646,7 +2646,7 @@ static void __init serial8250_isa_init_p
+ {
+ struct uart_8250_port *up;
+ static int first = 1;
+- int i;
++ int i, irqflag = 0;
+
+ if (!first)
+ return;
+@@ -2670,6 +2670,9 @@ static void __init serial8250_isa_init_p
+ up->port.ops = &serial8250_pops;
+ }
+
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
+ for (i = 0, up = serial8250_ports;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
+ i++, up++) {
+@@ -2683,8 +2686,7 @@ static void __init serial8250_isa_init_p
+ up->port.iotype = old_serial_port[i].io_type;
+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_from_upio(&up->port);
+- if (share_irqs)
+- up->port.irqflags |= IRQF_SHARED;
++ up->port.irqflags |= irqflag;
+ }
+ }
+
+@@ -2940,10 +2942,13 @@ static int __devinit serial8250_probe(st
+ {
+ struct plat_serial8250_port *p = dev->dev.platform_data;
+ struct uart_port port;
+- int ret, i;
++ int ret, i, irqflag = 0;
+
+ memset(&port, 0, sizeof(struct uart_port));
+
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
+ for (i = 0; p && p->flags != 0; p++, i++) {
+ port.iobase = p->iobase;
+ port.membase = p->membase;
+@@ -2960,8 +2965,7 @@ static int __devinit serial8250_probe(st
+ port.serial_in = p->serial_in;
+ port.serial_out = p->serial_out;
+ port.dev = &dev->dev;
+- if (share_irqs)
+- port.irqflags |= IRQF_SHARED;
++ port.irqflags |= irqflag;
+ ret = serial8250_register_port(&port);
+ if (ret < 0) {
+ dev_err(&dev->dev, "unable to register port at index %d "
diff --git a/tty/serial-cascade-needless-conditionals.patch b/tty/serial-cascade-needless-conditionals.patch
new file mode 100644
index 00000000000000..a3ac4ac1c8db32
--- /dev/null
+++ b/tty/serial-cascade-needless-conditionals.patch
@@ -0,0 +1,55 @@
+From andre.goddard@gmail.com Tue Oct 27 10:42:56 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 11:18:26 -0200
+Subject: serial: cascade needless conditionals
+To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250618h3edce547y41a8dd03e4fb4e71@mail.gmail.com>
+
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *por
+
+ if (flags == UPF_SPD_HI)
+ altbaud = 57600;
+- if (flags == UPF_SPD_VHI)
++ else if (flags == UPF_SPD_VHI)
+ altbaud = 115200;
+- if (flags == UPF_SPD_SHI)
++ else if (flags == UPF_SPD_SHI)
+ altbaud = 230400;
+- if (flags == UPF_SPD_WARP)
++ else if (flags == UPF_SPD_WARP)
+ altbaud = 460800;
+
+ for (try = 0; try < 2; try++) {
+@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+ uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
+-
+ /* Handle transition away from B0 status */
+- if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
++ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+ unsigned int mask = TIOCM_DTR;
+ if (!(cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags))
+@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_
+ __uart_start(tty);
+ spin_unlock_irqrestore(&state->uart_port->lock, flags);
+ }
+-
+ /* Handle turning on CRTSCTS */
+- if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
++ else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+ spin_lock_irqsave(&state->uart_port->lock, flags);
+ if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
+ tty->hw_stopped = 1;
diff --git a/tty/serial-fix-null-pointer-dereference.patch b/tty/serial-fix-null-pointer-dereference.patch
new file mode 100644
index 00000000000000..772ff351c318bc
--- /dev/null
+++ b/tty/serial-fix-null-pointer-dereference.patch
@@ -0,0 +1,71 @@
+From andre.goddard@gmail.com Tue Oct 27 10:42:06 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 11:16:32 -0200
+Subject: serial: fix NULL pointer dereference
+To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250616g8f204d2h471bd4d511a4816@mail.gmail.com>
+
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+
+If kzalloc() or alloc_tty_driver() fails, we call:
+ put_tty_driver(normal = NULL).
+
+Then:
+ put_tty_driver -> tty_driver_kref_put -> kref_put(&NULL->kref, ...)
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -2344,7 +2344,7 @@ static const struct tty_operations uart_
+ */
+ int uart_register_driver(struct uart_driver *drv)
+ {
+- struct tty_driver *normal = NULL;
++ struct tty_driver *normal;
+ int i, retval;
+
+ BUG_ON(drv->state);
+@@ -2354,13 +2354,12 @@ int uart_register_driver(struct uart_dri
+ * we have a large number of ports to handle.
+ */
+ drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+- retval = -ENOMEM;
+ if (!drv->state)
+ goto out;
+
+- normal = alloc_tty_driver(drv->nr);
++ normal = alloc_tty_driver(drv->nr);
+ if (!normal)
+- goto out;
++ goto out_kfree;
+
+ drv->tty_driver = normal;
+
+@@ -2393,12 +2392,14 @@ int uart_register_driver(struct uart_dri
+ }
+
+ retval = tty_register_driver(normal);
+- out:
+- if (retval < 0) {
+- put_tty_driver(normal);
+- kfree(drv->state);
+- }
+- return retval;
++ if (retval >= 0)
++ return retval;
++
++ put_tty_driver(normal);
++out_kfree:
++ kfree(drv->state);
++out:
++ return -ENOMEM;
+ }
+
+ /**
diff --git a/tty/tty_port-add-tty_port_open-helper.patch b/tty/tty_port-add-tty_port_open-helper.patch
new file mode 100644
index 00000000000000..968fa62f0458f4
--- /dev/null
+++ b/tty/tty_port-add-tty_port_open-helper.patch
@@ -0,0 +1,174 @@
+From alan@linux.intel.com Tue Oct 27 10:03:02 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:11 +0100
+Subject: tty_port: add "tty_port_open" helper
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150555.9431.34664.stgit@localhost.localdomain>
+
+
+For the moment this just moves the USB logic over and fixes the 'what if
+we open and hangup at the same time' race noticed by Oliver Neukum.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/char/tty_port.c | 36 ++++++++++++++++++++++++++++-
+ drivers/usb/serial/usb-serial.c | 49 ++++++++++++++++------------------------
+ include/linux/tty.h | 10 +++++++-
+ 3 files changed, 64 insertions(+), 31 deletions(-)
+
+--- a/drivers/char/tty_port.c
++++ b/drivers/char/tty_port.c
+@@ -99,10 +99,11 @@ EXPORT_SYMBOL(tty_port_tty_set);
+
+ static void tty_port_shutdown(struct tty_port *port)
+ {
++ mutex_lock(&port->mutex);
+ if (port->ops->shutdown &&
+ test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+ port->ops->shutdown(port);
+-
++ mutex_unlock(&port->mutex);
+ }
+
+ /**
+@@ -375,3 +376,36 @@ void tty_port_close(struct tty_port *por
+ tty_port_tty_set(port, NULL);
+ }
+ EXPORT_SYMBOL(tty_port_close);
++
++int tty_port_open(struct tty_port *port, struct tty_struct *tty,
++ struct file *filp)
++{
++ spin_lock_irq(&port->lock);
++ if (!tty_hung_up_p(filp))
++ ++port->count;
++ spin_unlock_irq(&port->lock);
++ tty_port_tty_set(port, tty);
++
++ /*
++ * Do the device-specific open only if the hardware isn't
++ * already initialized. Serialize open and shutdown using the
++ * port mutex.
++ */
++
++ mutex_lock(&port->mutex);
++
++ if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
++ if (port->ops->activate) {
++ int retval = port->ops->activate(port, tty);
++ if (retval) {
++ mutex_unlock(&port->mutex);
++ return retval;
++ }
++ }
++ set_bit(ASYNCB_INITIALIZED, &port->flags);
++ }
++ mutex_unlock(&port->mutex);
++ return tty_port_block_til_ready(port, tty, filp);
++}
++
++EXPORT_SYMBOL(tty_port_open);
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -247,41 +247,31 @@ static int serial_install(struct tty_dri
+ return retval;
+ }
+
+-static int serial_open(struct tty_struct *tty, struct file *filp)
++static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+ {
+- struct usb_serial_port *port = tty->driver_data;
++ struct usb_serial_port *port =
++ container_of(tport, struct usb_serial_port, port);
+ struct usb_serial *serial = port->serial;
+ int retval;
+
+- dbg("%s - port %d", __func__, port->number);
+-
+- spin_lock_irq(&port->port.lock);
+- if (!tty_hung_up_p(filp))
+- ++port->port.count;
+- spin_unlock_irq(&port->port.lock);
+- tty_port_tty_set(&port->port, tty);
++ if (mutex_lock_interruptible(&port->mutex))
++ return -ERESTARTSYS;
++ mutex_lock(&serial->disc_mutex);
++ if (serial->disconnected)
++ retval = -ENODEV;
++ else
++ retval = port->serial->type->open(tty, port);
++ mutex_unlock(&serial->disc_mutex);
++ mutex_unlock(&port->mutex);
++ return retval;
++}
+
+- /* Do the device-specific open only if the hardware isn't
+- * already initialized.
+- */
+- if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+- if (mutex_lock_interruptible(&port->mutex))
+- return -ERESTARTSYS;
+- mutex_lock(&serial->disc_mutex);
+- if (serial->disconnected)
+- retval = -ENODEV;
+- else
+- retval = port->serial->type->open(tty, port);
+- mutex_unlock(&serial->disc_mutex);
+- mutex_unlock(&port->mutex);
+- if (retval)
+- return retval;
+- set_bit(ASYNCB_INITIALIZED, &port->port.flags);
+- }
++static int serial_open(struct tty_struct *tty, struct file *filp)
++{
++ struct usb_serial_port *port = tty->driver_data;
+
+- /* Now do the correct tty layer semantics */
+- retval = tty_port_block_til_ready(&port->port, tty, filp);
+- return retval;
++ dbg("%s - port %d", __func__, port->number);
++ return tty_port_open(&port->port, tty, filp);
+ }
+
+ /**
+@@ -725,6 +715,7 @@ static void serial_dtr_rts(struct tty_po
+ static const struct tty_port_operations serial_port_ops = {
+ .carrier_raised = serial_carrier_raised,
+ .dtr_rts = serial_dtr_rts,
++ .activate = serial_activate,
+ };
+
+ int usb_serial_probe(struct usb_interface *interface,
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -190,9 +190,15 @@ struct tty_port_operations {
+ /* Control the DTR line */
+ void (*dtr_rts)(struct tty_port *port, int raise);
+ /* Called when the last close completes or a hangup finishes
+- IFF the port was initialized. Do not use to free resources */
++ IFF the port was initialized. Do not use to free resources. Called
++ under the port mutex to serialize against activate/shutdowns */
+ void (*shutdown)(struct tty_port *port);
+ void (*drop)(struct tty_port *port);
++ /* Called under the port mutex from tty_port_open, serialized using
++ the port mutex */
++ /* FIXME: long term getting the tty argument *out* of this would be
++ good for consoles */
++ int (*activate)(struct tty_port *port, struct tty_struct *tty);
+ };
+
+ struct tty_port {
+@@ -467,6 +473,8 @@ extern int tty_port_close_start(struct t
+ extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
+ extern void tty_port_close(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp);
++extern int tty_port_open(struct tty_port *port,
++ struct tty_struct *tty, struct file *filp);
+ extern inline int tty_port_users(struct tty_port *port)
+ {
+ return port->count + port->blocked_open;
diff --git a/tty/tty_port-coding-style-cleaning-pass.patch b/tty/tty_port-coding-style-cleaning-pass.patch
new file mode 100644
index 00000000000000..8c322f6308d063
--- /dev/null
+++ b/tty/tty_port-coding-style-cleaning-pass.patch
@@ -0,0 +1,98 @@
+From alan@linux.intel.com Tue Oct 27 10:03:21 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:21 +0100
+Subject: tty_port: coding style cleaning pass
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150616.9431.29417.stgit@localhost.localdomain>
+
+
+Mind the hoover wire...
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/tty_port.c | 25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+--- a/drivers/char/tty_port.c
++++ b/drivers/char/tty_port.c
+@@ -199,7 +199,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
+ * management of these lines. Note that the dtr/rts raise is done each
+ * iteration as a hangup may have previously dropped them while we wait.
+ */
+-
++
+ int tty_port_block_til_ready(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp)
+ {
+@@ -248,7 +248,8 @@ int tty_port_block_til_ready(struct tty_
+ tty_port_raise_dtr_rts(port);
+
+ prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
+- /* Check for a hangup or uninitialised port. Return accordingly */
++ /* Check for a hangup or uninitialised port.
++ Return accordingly */
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+@@ -280,11 +281,11 @@ int tty_port_block_til_ready(struct tty_
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ spin_unlock_irqrestore(&port->lock, flags);
+ return retval;
+-
+ }
+ EXPORT_SYMBOL(tty_port_block_til_ready);
+
+-int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
++int tty_port_close_start(struct tty_port *port,
++ struct tty_struct *tty, struct file *filp)
+ {
+ unsigned long flags;
+
+@@ -294,7 +295,7 @@ int tty_port_close_start(struct tty_port
+ return 0;
+ }
+
+- if( tty->count == 1 && port->count != 1) {
++ if (tty->count == 1 && port->count != 1) {
+ printk(KERN_WARNING
+ "tty_port_close_start: tty->count = 1 port count = %d.\n",
+ port->count);
+@@ -326,8 +327,8 @@ int tty_port_close_start(struct tty_port
+ long timeout;
+
+ if (bps > 1200)
+- timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
+- HZ / 10);
++ timeout = max_t(long,
++ (HZ * 10 * port->drain_delay) / bps, HZ / 10);
+ else
+ timeout = 2 * HZ;
+ schedule_timeout_interruptible(timeout);
+@@ -378,7 +379,7 @@ void tty_port_close(struct tty_port *por
+ EXPORT_SYMBOL(tty_port_close);
+
+ int tty_port_open(struct tty_port *port, struct tty_struct *tty,
+- struct file *filp)
++ struct file *filp)
+ {
+ spin_lock_irq(&port->lock);
+ if (!tty_hung_up_p(filp))
+@@ -398,10 +399,10 @@ int tty_port_open(struct tty_port *port,
+ if (port->ops->activate) {
+ int retval = port->ops->activate(port, tty);
+ if (retval) {
+- mutex_unlock(&port->mutex);
+- return retval;
+- }
+- }
++ mutex_unlock(&port->mutex);
++ return retval;
++ }
++ }
+ set_bit(ASYNCB_INITIALIZED, &port->flags);
+ }
+ mutex_unlock(&port->mutex);
diff --git a/tty/usb_serial-kill-port-mutex.patch b/tty/usb_serial-kill-port-mutex.patch
new file mode 100644
index 00000000000000..32b861dffc5506
--- /dev/null
+++ b/tty/usb_serial-kill-port-mutex.patch
@@ -0,0 +1,68 @@
+From alan@linux.intel.com Tue Oct 27 10:07:10 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:46 +0100
+Subject: usb_serial: Kill port mutex
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150641.9431.67880.stgit@localhost.localdomain>
+
+
+The tty port has a port mutex used for all the port related locking so we
+don't need the one in the USB serial layer any more.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/opticon.c | 4 ++--
+ drivers/usb/serial/usb-serial.c | 1 -
+ include/linux/usb/serial.h | 3 ---
+ 3 files changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -501,12 +501,12 @@ static int opticon_resume(struct usb_int
+ struct usb_serial_port *port = serial->port[0];
+ int result;
+
+- mutex_lock(&port->mutex);
++ mutex_lock(&port->port.mutex);
+ if (port->port.count)
+ result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
+ else
+ result = 0;
+- mutex_unlock(&port->mutex);
++ mutex_unlock(&port->port.mutex);
+ return result;
+ }
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -897,7 +897,6 @@ int usb_serial_probe(struct usb_interfac
+ spin_lock_init(&port->lock);
+ /* Keep this for private driver use for the moment but
+ should probably go away */
+- mutex_init(&port->mutex);
+ INIT_WORK(&port->work, usb_serial_port_work);
+ serial->port[i] = port;
+ port->dev.parent = &interface->dev;
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -39,8 +39,6 @@ enum port_dev_state {
+ * @serial: pointer back to the struct usb_serial owner of this port.
+ * @port: pointer to the corresponding tty_port for this port.
+ * @lock: spinlock to grab when updating portions of this structure.
+- * @mutex: mutex used to synchronize serial_open() and serial_close()
+- * access for this port.
+ * @number: the number of the port (the minor number).
+ * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
+ * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
+@@ -77,7 +75,6 @@ struct usb_serial_port {
+ struct usb_serial *serial;
+ struct tty_port port;
+ spinlock_t lock;
+- struct mutex mutex;
+ unsigned char number;
+
+ unsigned char *interrupt_in_buffer;
diff --git a/tty/usb_serial-use-the-shutdown-operation.patch b/tty/usb_serial-use-the-shutdown-operation.patch
new file mode 100644
index 00000000000000..0def7d620d5395
--- /dev/null
+++ b/tty/usb_serial-use-the-shutdown-operation.patch
@@ -0,0 +1,124 @@
+From alan@linux.intel.com Tue Oct 27 10:05:50 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:36 +0100
+Subject: [PATCH 3/5] usb_serial: Use the shutdown() operation
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150626.9431.34542.stgit@localhost.localdomain>
+
+
+As Alan Stern pointed out - now we have tty_port_open the shutdown method
+and locking allow us to whack the other bits into the full helper methods
+and provide a shutdown op which the tty port code will synchronize with
+setup for us.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/usb-serial.c | 39 +++++++++++----------------------------
+ 1 file changed, 11 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -254,15 +254,12 @@ static int serial_activate(struct tty_po
+ struct usb_serial *serial = port->serial;
+ int retval;
+
+- if (mutex_lock_interruptible(&port->mutex))
+- return -ERESTARTSYS;
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected)
+ retval = -ENODEV;
+ else
+ retval = port->serial->type->open(tty, port);
+ mutex_unlock(&serial->disc_mutex);
+- mutex_unlock(&port->mutex);
+ return retval;
+ }
+
+@@ -276,57 +273,40 @@ static int serial_open(struct tty_struct
+
+ /**
+ * serial_down - shut down hardware
+- * @port: port to shut down
++ * @tport: tty port to shut down
+ *
+ * Shut down a USB serial port unless it is the console. We never
+- * shut down the console hardware as it will always be in use.
++ * shut down the console hardware as it will always be in use. Serialized
++ * against activate by the tport mutex and kept to matching open/close pairs
++ * of calls by the ASYNCB_INITIALIZED flag.
+ */
+-static void serial_down(struct usb_serial_port *port)
++static void serial_down(struct tty_port *tport)
+ {
++ struct usb_serial_port *port =
++ container_of(tport, struct usb_serial_port, port);
+ struct usb_serial_driver *drv = port->serial->type;
+-
+ /*
+ * The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
+ if (port->console)
+ return;
+-
+- /* Don't call the close method if the hardware hasn't been
+- * initialized.
+- */
+- if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
+- return;
+-
+- mutex_lock(&port->mutex);
+ if (drv->close)
+ drv->close(port);
+- mutex_unlock(&port->mutex);
+ }
+
+ static void serial_hangup(struct tty_struct *tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+-
+ dbg("%s - port %d", __func__, port->number);
+-
+- serial_down(port);
+ tty_port_hangup(&port->port);
+ }
+
+ static void serial_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+-
+ dbg("%s - port %d", __func__, port->number);
+-
+- if (tty_hung_up_p(filp))
+- return;
+- if (tty_port_close_start(&port->port, tty, filp) == 0)
+- return;
+- serial_down(port);
+- tty_port_close_end(&port->port, tty);
+- tty_port_tty_set(&port->port, NULL);
++ tty_port_close(&port->port, tty, filp);
+ }
+
+ /**
+@@ -716,6 +696,7 @@ static const struct tty_port_operations
+ .carrier_raised = serial_carrier_raised,
+ .dtr_rts = serial_dtr_rts,
+ .activate = serial_activate,
++ .shutdown = serial_down,
+ };
+
+ int usb_serial_probe(struct usb_interface *interface,
+@@ -914,6 +895,8 @@ int usb_serial_probe(struct usb_interfac
+ port->port.ops = &serial_port_ops;
+ port->serial = serial;
+ spin_lock_init(&port->lock);
++ /* Keep this for private driver use for the moment but
++ should probably go away */
+ mutex_init(&port->mutex);
+ INIT_WORK(&port->work, usb_serial_port_work);
+ serial->port[i] = port;
diff --git a/usb.current/usb-option-tlaytech-tue800-support.patch b/usb.current/usb-option-tlaytech-tue800-support.patch
new file mode 100644
index 00000000000000..b3d50d9b214f83
--- /dev/null
+++ b/usb.current/usb-option-tlaytech-tue800-support.patch
@@ -0,0 +1,40 @@
+From bryan.wu@canonical.com Tue Oct 27 10:35:48 2009
+From: Bryan Wu <bryan.wu@canonical.com>
+Date: Thu, 22 Oct 2009 15:00:36 +0800
+Subject: USB: option: TLAYTECH TUE800 support
+To: smurf@smurf.noris.de
+Cc: linux-usb@vger.kernel.org, gregkh@suse.de, linux-kernel@vger.kernel.org
+Message-ID: <1256194836-15733-1-git-send-email-bryan.wu@canonical.com>
+
+
+Add ID for Tlaytech TUE800 CDMA modem to the option driver.
+
+Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
+Acked-By: Matthias Urlichs <matthias@urlichs.de>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -315,6 +315,9 @@ static int option_resume(struct usb_ser
+ #define QISDA_PRODUCT_H20_4515 0x4515
+ #define QISDA_PRODUCT_H20_4519 0x4519
+
++/* TLAYTECH PRODUCTS */
++#define TLAYTECH_VENDOR_ID 0x20B9
++#define TLAYTECH_PRODUCT_TEU800 0x1682
+
+ /* TOSHIBA PRODUCTS */
+ #define TOSHIBA_VENDOR_ID 0x0930
+@@ -593,6 +596,7 @@ static struct usb_device_id option_ids[]
+ { 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) },
++ { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch b/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch
new file mode 100644
index 00000000000000..2ff23a249f8137
--- /dev/null
+++ b/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch
@@ -0,0 +1,57 @@
+From shimoda.yoshihiro@renesas.com Tue Oct 27 10:23:57 2009
+From: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+Date: Wed, 21 Oct 2009 20:33:39 +0900
+Subject: USB: r8a66597-hcd: fix cannot detect a device when uses_new_polling is set
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Message-ID: <4ADEF193.30204@renesas.com>
+
+
+Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/r8a66597-hcd.c | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct
+ if (syssts == SE0) {
+ r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
+ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+- return;
+- }
++ } else {
++ if (syssts == FS_JSTS)
++ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
++ else if (syssts == LS_JSTS)
++ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+
+- if (syssts == FS_JSTS)
+- r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+- else if (syssts == LS_JSTS)
+- r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
++ r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
++ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+
+- r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+- r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
++ if (r8a66597->bus_suspended)
++ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
++ }
+
+- if (r8a66597->bus_suspended)
+- usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
++ usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
+ }
+
+ /* this function must be called with interrupt disabled */
+@@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct
+ u16 speed = get_rh_usb_speed(r8a66597, port);
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
++ rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) |
++ (1 << USB_PORT_FEAT_LOWSPEED));
+ if (speed == HSMODE)
+ rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
+ else if (speed == LSMODE)
diff --git a/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch b/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch
new file mode 100644
index 00000000000000..6aa61e5a1d0af9
--- /dev/null
+++ b/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch
@@ -0,0 +1,82 @@
+From epasheva@sierrawireless.com Tue Oct 27 10:12:48 2009
+From: Elina Pasheva <epasheva@sierrawireless.com>
+Date: Fri, 16 Oct 2009 12:04:54 -0700
+Subject: USB: serial: sierra driver send_setup() autopm fix
+To: <gregkh@suse.de>
+Cc: <epasheva@sierrawireless.com>, <rfiler@sierrawireless.com>
+Message-ID: <1255719894.23492.5.camel@Linuxdev4-laptop>
+
+
+From: Elina Pasheva <epasheva@sierrawireless.com>
+
+This patch presents a fix for the autosuspend feature implementation in
+sierra usb serial driver for function sierra_send_setup(). Because it
+is possible to call sierra_send_setup() before sierra_open() or after
+sierra_close() we added a get/put interface activity to assure that the
+usb control can happen even when the device is autosuspended.
+
+Signed-off-by: Elina Pasheva <epasheva@sierrawireless.com>
+Tested-by: Matthew Safar <msafar@sierrawireless.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/sierra.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -296,7 +296,6 @@ struct sierra_port_private {
+ int dsr_state;
+ int dcd_state;
+ int ri_state;
+-
+ unsigned int opened:1;
+ };
+
+@@ -306,6 +305,8 @@ static int sierra_send_setup(struct usb_
+ struct sierra_port_private *portdata;
+ __u16 interface = 0;
+ int val = 0;
++ int do_send = 0;
++ int retval;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+@@ -324,10 +325,7 @@ static int sierra_send_setup(struct usb_
+ */
+ if (port->interrupt_in_urb) {
+ /* send control message */
+- return usb_control_msg(serial->dev,
+- usb_rcvctrlpipe(serial->dev, 0),
+- 0x22, 0x21, val, interface,
+- NULL, 0, USB_CTRL_SET_TIMEOUT);
++ do_send = 1;
+ }
+ }
+
+@@ -339,12 +337,18 @@ static int sierra_send_setup(struct usb_
+ interface = 1;
+ else if (port->bulk_out_endpointAddress == 5)
+ interface = 2;
+- return usb_control_msg(serial->dev,
+- usb_rcvctrlpipe(serial->dev, 0),
+- 0x22, 0x21, val, interface,
+- NULL, 0, USB_CTRL_SET_TIMEOUT);
++
++ do_send = 1;
+ }
+- return 0;
++ if (!do_send)
++ return 0;
++
++ usb_autopm_get_interface(serial->interface);
++ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
++ usb_autopm_put_interface(serial->interface);
++
++ return retval;
+ }
+
+ static void sierra_set_termios(struct tty_struct *tty,
diff --git a/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch b/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch
new file mode 100644
index 00000000000000..d8ac4ccc24891b
--- /dev/null
+++ b/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch
@@ -0,0 +1,797 @@
+From felipe.balbi@nokia.com Tue Oct 27 10:11:17 2009
+From: Felipe Balbi <felipe.balbi@nokia.com>
+Date: Wed, 14 Oct 2009 11:44:14 +0300
+Subject: USB: host: ehci: introduce omap ehci-hcd driver
+To: linux-usb@vger.kernel.org
+Cc: Felipe Balbi <felipe.balbi@nokia.com>, Vikram Pandita <vikram.pandita@ti.com>, Ajay Kumar Gupta <ajay.gupta@ti.com>, Anand Gadiyar <gadiyar@ti.com>
+Message-ID: <1255509855-9046-1-git-send-email-felipe.balbi@nokia.com>
+
+
+this driver has been sitting in linux-omap tree for quite
+some time. It adds support for omap's ehci controller.
+
+Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-hcd.c | 5
+ drivers/usb/host/ehci-omap.c | 755 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 760 insertions(+)
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1108,6 +1108,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver
+ #endif
+
++#ifdef CONFIG_ARCH_OMAP34XX
++#include "ehci-omap.c"
++#define PLATFORM_DRIVER ehci_hcd_omap_driver
++#endif
++
+ #ifdef CONFIG_PPC_PS3
+ #include "ehci-ps3.c"
+ #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
+--- /dev/null
++++ b/drivers/usb/host/ehci-omap.c
+@@ -0,0 +1,755 @@
++/*
++ * ehci-omap.c - driver for USBHOST on OMAP 34xx processor
++ *
++ * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller
++ * Tested on OMAP3430 ES2.0 SDP
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Author: Vikram Pandita <vikram.pandita@ti.com>
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
++ *
++ * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * TODO (last updated Feb 23rd, 2009):
++ * - add kernel-doc
++ * - enable AUTOIDLE
++ * - move DPLL5 programming to clock fw
++ * - add suspend/resume
++ * - move workarounds to board-files
++ */
++
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/gpio.h>
++#include <mach/usb.h>
++
++/*
++ * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
++ * Use ehci_omap_readl()/ehci_omap_writel() functions
++ */
++
++/* TLL Register Set */
++#define OMAP_USBTLL_REVISION (0x00)
++#define OMAP_USBTLL_SYSCONFIG (0x10)
++#define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8)
++#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3)
++#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2)
++#define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1)
++#define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0)
++
++#define OMAP_USBTLL_SYSSTATUS (0x14)
++#define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0)
++
++#define OMAP_USBTLL_IRQSTATUS (0x18)
++#define OMAP_USBTLL_IRQENABLE (0x1C)
++
++#define OMAP_TLL_SHARED_CONF (0x30)
++#define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6)
++#define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5)
++#define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2)
++#define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1)
++#define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0)
++
++#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num)
++#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11)
++#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10)
++#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9)
++#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8)
++#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0)
++
++#define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num)
++#define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num)
++#define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num)
++#define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num)
++#define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num)
++#define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num)
++#define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num)
++#define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num)
++#define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num)
++
++#define OMAP_TLL_CHANNEL_COUNT 3
++#define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1)
++#define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2)
++#define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4)
++
++/* UHH Register Set */
++#define OMAP_UHH_REVISION (0x00)
++#define OMAP_UHH_SYSCONFIG (0x10)
++#define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12)
++#define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8)
++#define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3)
++#define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2)
++#define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1)
++#define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0)
++
++#define OMAP_UHH_SYSSTATUS (0x14)
++#define OMAP_UHH_HOSTCONFIG (0x40)
++#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0)
++#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0)
++#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11)
++#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12)
++#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2)
++#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3)
++#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4)
++#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5)
++#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8)
++#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9)
++#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10)
++
++#define OMAP_UHH_DEBUG_CSR (0x44)
++
++/* EHCI Register Set */
++#define EHCI_INSNREG05_ULPI (0xA4)
++#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31
++#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24
++#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22
++#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16
++#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8
++#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0
++
++/*-------------------------------------------------------------------------*/
++
++static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
++{
++ __raw_writel(val, base + reg);
++}
++
++static inline u32 ehci_omap_readl(void __iomem *base, u32 reg)
++{
++ return __raw_readl(base + reg);
++}
++
++static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val)
++{
++ __raw_writeb(val, base + reg);
++}
++
++static inline u8 ehci_omap_readb(void __iomem *base, u8 reg)
++{
++ return __raw_readb(base + reg);
++}
++
++/*-------------------------------------------------------------------------*/
++
++struct ehci_hcd_omap {
++ struct ehci_hcd *ehci;
++ struct device *dev;
++
++ struct clk *usbhost_ick;
++ struct clk *usbhost2_120m_fck;
++ struct clk *usbhost1_48m_fck;
++ struct clk *usbtll_fck;
++ struct clk *usbtll_ick;
++
++ /* FIXME the following two workarounds are
++ * board specific not silicon-specific so these
++ * should be moved to board-file instead.
++ *
++ * Maybe someone from TI will know better which
++ * board is affected and needs the workarounds
++ * to be applied
++ */
++
++ /* gpio for resetting phy */
++ int reset_gpio_port[OMAP3_HS_USB_PORTS];
++
++ /* phy reset workaround */
++ int phy_reset;
++
++ /* desired phy_mode: TLL, PHY */
++ enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS];
++
++ void __iomem *uhh_base;
++ void __iomem *tll_base;
++ void __iomem *ehci_base;
++};
++
++/*-------------------------------------------------------------------------*/
++
++static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask)
++{
++ unsigned reg;
++ int i;
++
++ /* Program the 3 TLL channels upfront */
++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
++
++ /* Disable AutoIdle, BitStuffing and use SDR Mode */
++ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
++ | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
++ | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
++ ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
++ }
++
++ /* Program Common TLL register */
++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
++ reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
++ | OMAP_TLL_SHARED_CONF_USB_DIVRATION
++ | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN);
++ reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
++
++ ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
++
++ /* Enable channels now */
++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
++
++ /* Enable only the reg that is needed */
++ if (!(tll_channel_mask & 1<<i))
++ continue;
++
++ reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
++ ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
++
++ ehci_omap_writeb(omap->tll_base,
++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
++ dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n",
++ i+1, ehci_omap_readb(omap->tll_base,
++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
++ }
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* omap_start_ehc
++ * - Start the TI USBHOST controller
++ */
++static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
++{
++ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
++ u8 tll_ch_mask = 0;
++ unsigned reg = 0;
++ int ret = 0;
++
++ dev_dbg(omap->dev, "starting TI EHCI USB Controller\n");
++
++ /* Enable Clocks for USBHOST */
++ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
++ if (IS_ERR(omap->usbhost_ick)) {
++ ret = PTR_ERR(omap->usbhost_ick);
++ goto err_host_ick;
++ }
++ clk_enable(omap->usbhost_ick);
++
++ omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck");
++ if (IS_ERR(omap->usbhost2_120m_fck)) {
++ ret = PTR_ERR(omap->usbhost2_120m_fck);
++ goto err_host_120m_fck;
++ }
++ clk_enable(omap->usbhost2_120m_fck);
++
++ omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck");
++ if (IS_ERR(omap->usbhost1_48m_fck)) {
++ ret = PTR_ERR(omap->usbhost1_48m_fck);
++ goto err_host_48m_fck;
++ }
++ clk_enable(omap->usbhost1_48m_fck);
++
++ if (omap->phy_reset) {
++ /* Refer: ISSUE1 */
++ if (gpio_is_valid(omap->reset_gpio_port[0])) {
++ gpio_request(omap->reset_gpio_port[0],
++ "USB1 PHY reset");
++ gpio_direction_output(omap->reset_gpio_port[0], 0);
++ }
++
++ if (gpio_is_valid(omap->reset_gpio_port[1])) {
++ gpio_request(omap->reset_gpio_port[1],
++ "USB2 PHY reset");
++ gpio_direction_output(omap->reset_gpio_port[1], 0);
++ }
++
++ /* Hold the PHY in RESET for enough time till DIR is high */
++ udelay(10);
++ }
++
++ /* Configure TLL for 60Mhz clk for ULPI */
++ omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
++ if (IS_ERR(omap->usbtll_fck)) {
++ ret = PTR_ERR(omap->usbtll_fck);
++ goto err_tll_fck;
++ }
++ clk_enable(omap->usbtll_fck);
++
++ omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
++ if (IS_ERR(omap->usbtll_ick)) {
++ ret = PTR_ERR(omap->usbtll_ick);
++ goto err_tll_ick;
++ }
++ clk_enable(omap->usbtll_ick);
++
++ /* perform TLL soft reset, and wait until reset is complete */
++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
++ OMAP_USBTLL_SYSCONFIG_SOFTRESET);
++
++ /* Wait for TLL reset to complete */
++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
++ & OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout)) {
++ dev_dbg(omap->dev, "operation timed out\n");
++ ret = -EINVAL;
++ goto err_sys_status;
++ }
++ }
++
++ dev_dbg(omap->dev, "TLL RESET DONE\n");
++
++ /* (1<<3) = no idle mode only for initial debugging */
++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
++ OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
++ OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
++ OMAP_USBTLL_SYSCONFIG_CACTIVITY);
++
++
++ /* Put UHH in NoIdle/NoStandby mode */
++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
++ reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
++ | OMAP_UHH_SYSCONFIG_SIDLEMODE
++ | OMAP_UHH_SYSCONFIG_CACTIVITY
++ | OMAP_UHH_SYSCONFIG_MIDLEMODE);
++ reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
++
++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
++
++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
++
++ /* setup ULPI bypass and burst configurations */
++ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
++ | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
++ | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
++ reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
++
++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
++ reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
++ reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
++ reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
++
++ /* Bypass the TLL module for PHY mode operation */
++ if (omap_rev() <= OMAP3430_REV_ES2_1) {
++ dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n");
++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
++ else
++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
++ } else {
++ dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
++ else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
++
++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
++ else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
++
++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)
++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
++ else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
++
++ }
++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
++ dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
++
++
++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
++
++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
++ tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK;
++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
++ tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK;
++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
++ tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
++
++ /* Enable UTMI mode for required TLL channels */
++ omap_usb_utmi_init(omap, tll_ch_mask);
++ }
++
++ if (omap->phy_reset) {
++ /* Refer ISSUE1:
++ * Hold the PHY in RESET for enough time till
++ * PHY is settled and ready
++ */
++ udelay(10);
++
++ if (gpio_is_valid(omap->reset_gpio_port[0]))
++ gpio_set_value(omap->reset_gpio_port[0], 1);
++
++ if (gpio_is_valid(omap->reset_gpio_port[1]))
++ gpio_set_value(omap->reset_gpio_port[1], 1);
++ }
++
++ return 0;
++
++err_sys_status:
++ clk_disable(omap->usbtll_ick);
++ clk_put(omap->usbtll_ick);
++
++err_tll_ick:
++ clk_disable(omap->usbtll_fck);
++ clk_put(omap->usbtll_fck);
++
++err_tll_fck:
++ clk_disable(omap->usbhost1_48m_fck);
++ clk_put(omap->usbhost1_48m_fck);
++
++ if (omap->phy_reset) {
++ if (gpio_is_valid(omap->reset_gpio_port[0]))
++ gpio_free(omap->reset_gpio_port[0]);
++
++ if (gpio_is_valid(omap->reset_gpio_port[1]))
++ gpio_free(omap->reset_gpio_port[1]);
++ }
++
++err_host_48m_fck:
++ clk_disable(omap->usbhost2_120m_fck);
++ clk_put(omap->usbhost2_120m_fck);
++
++err_host_120m_fck:
++ clk_disable(omap->usbhost_ick);
++ clk_put(omap->usbhost_ick);
++
++err_host_ick:
++ return ret;
++}
++
++static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
++{
++ unsigned long timeout = jiffies + msecs_to_jiffies(100);
++
++ dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
++
++ /* Reset OMAP modules for insmod/rmmod to work */
++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
++ OMAP_UHH_SYSCONFIG_SOFTRESET);
++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
++ & (1 << 0))) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ dev_dbg(omap->dev, "operation timed out\n");
++ }
++
++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
++ & (1 << 1))) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ dev_dbg(omap->dev, "operation timed out\n");
++ }
++
++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
++ & (1 << 2))) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ dev_dbg(omap->dev, "operation timed out\n");
++ }
++
++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
++
++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
++ & (1 << 0))) {
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ dev_dbg(omap->dev, "operation timed out\n");
++ }
++
++ if (omap->usbtll_fck != NULL) {
++ clk_disable(omap->usbtll_fck);
++ clk_put(omap->usbtll_fck);
++ omap->usbtll_fck = NULL;
++ }
++
++ if (omap->usbhost_ick != NULL) {
++ clk_disable(omap->usbhost_ick);
++ clk_put(omap->usbhost_ick);
++ omap->usbhost_ick = NULL;
++ }
++
++ if (omap->usbhost1_48m_fck != NULL) {
++ clk_disable(omap->usbhost1_48m_fck);
++ clk_put(omap->usbhost1_48m_fck);
++ omap->usbhost1_48m_fck = NULL;
++ }
++
++ if (omap->usbhost2_120m_fck != NULL) {
++ clk_disable(omap->usbhost2_120m_fck);
++ clk_put(omap->usbhost2_120m_fck);
++ omap->usbhost2_120m_fck = NULL;
++ }
++
++ if (omap->usbtll_ick != NULL) {
++ clk_disable(omap->usbtll_ick);
++ clk_put(omap->usbtll_ick);
++ omap->usbtll_ick = NULL;
++ }
++
++ if (omap->phy_reset) {
++ if (gpio_is_valid(omap->reset_gpio_port[0]))
++ gpio_free(omap->reset_gpio_port[0]);
++
++ if (gpio_is_valid(omap->reset_gpio_port[1]))
++ gpio_free(omap->reset_gpio_port[1]);
++ }
++
++ dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
++}
++
++/*-------------------------------------------------------------------------*/
++
++static const struct hc_driver ehci_omap_hc_driver;
++
++/* configure so an HC device and id are always provided */
++/* always called with process context; sleeping is OK */
++
++/**
++ * ehci_hcd_omap_probe - initialize TI-based HCDs
++ *
++ * Allocates basic resources for this USB host controller, and
++ * then invokes the start() method for the HCD associated with it
++ * through the hotplug entry's driver_data.
++ */
++static int ehci_hcd_omap_probe(struct platform_device *pdev)
++{
++ struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
++ struct ehci_hcd_omap *omap;
++ struct resource *res;
++ struct usb_hcd *hcd;
++
++ int irq = platform_get_irq(pdev, 0);
++ int ret = -ENODEV;
++
++ if (!pdata) {
++ dev_dbg(&pdev->dev, "missing platform_data\n");
++ goto err_pdata;
++ }
++
++ if (usb_disabled())
++ goto err_disabled;
++
++ omap = kzalloc(sizeof(*omap), GFP_KERNEL);
++ if (!omap) {
++ ret = -ENOMEM;
++ goto err_create_hcd;
++ }
++
++ hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev,
++ dev_name(&pdev->dev));
++ if (!hcd) {
++ dev_dbg(&pdev->dev, "failed to create hcd with err %d\n", ret);
++ ret = -ENOMEM;
++ goto err_create_hcd;
++ }
++
++ platform_set_drvdata(pdev, omap);
++ omap->dev = &pdev->dev;
++ omap->phy_reset = pdata->phy_reset;
++ omap->reset_gpio_port[0] = pdata->reset_gpio_port[0];
++ omap->reset_gpio_port[1] = pdata->reset_gpio_port[1];
++ omap->reset_gpio_port[2] = pdata->reset_gpio_port[2];
++ omap->port_mode[0] = pdata->port_mode[0];
++ omap->port_mode[1] = pdata->port_mode[1];
++ omap->port_mode[2] = pdata->port_mode[2];
++ omap->ehci = hcd_to_ehci(hcd);
++ omap->ehci->sbrn = 0x20;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ hcd->rsrc_start = res->start;
++ hcd->rsrc_len = resource_size(res);
++
++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
++ if (!hcd->regs) {
++ dev_err(&pdev->dev, "EHCI ioremap failed\n");
++ ret = -ENOMEM;
++ goto err_ioremap;
++ }
++
++ /* we know this is the memory we want, no need to ioremap again */
++ omap->ehci->caps = hcd->regs;
++ omap->ehci_base = hcd->regs;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ omap->uhh_base = ioremap(res->start, resource_size(res));
++ if (!omap->uhh_base) {
++ dev_err(&pdev->dev, "UHH ioremap failed\n");
++ ret = -ENOMEM;
++ goto err_uhh_ioremap;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++ omap->tll_base = ioremap(res->start, resource_size(res));
++ if (!omap->tll_base) {
++ dev_err(&pdev->dev, "TLL ioremap failed\n");
++ ret = -ENOMEM;
++ goto err_tll_ioremap;
++ }
++
++ ret = omap_start_ehc(omap, hcd);
++ if (ret) {
++ dev_dbg(&pdev->dev, "failed to start ehci\n");
++ goto err_start;
++ }
++
++ omap->ehci->regs = hcd->regs
++ + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
++
++ /* cache this readonly data; minimize chip reads */
++ omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
++
++ /* SET 1 micro-frame Interrupt interval */
++ writel(readl(&omap->ehci->regs->command) | (1 << 16),
++ &omap->ehci->regs->command);
++
++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
++ if (ret) {
++ dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
++ goto err_add_hcd;
++ }
++
++ return 0;
++
++err_add_hcd:
++ omap_stop_ehc(omap, hcd);
++
++err_start:
++ iounmap(omap->tll_base);
++
++err_tll_ioremap:
++ iounmap(omap->uhh_base);
++
++err_uhh_ioremap:
++ iounmap(hcd->regs);
++
++err_ioremap:
++ usb_put_hcd(hcd);
++
++err_create_hcd:
++err_disabled:
++err_pdata:
++ return ret;
++}
++
++/* may be called without controller electrically present */
++/* may be called with controller, bus, and devices active */
++
++/**
++ * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
++ * @pdev: USB Host Controller being removed
++ *
++ * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking
++ * the HCD's stop() method. It is always called from a thread
++ * context, normally "rmmod", "apmd", or something similar.
++ */
++static int ehci_hcd_omap_remove(struct platform_device *pdev)
++{
++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
++
++ usb_remove_hcd(hcd);
++ omap_stop_ehc(omap, hcd);
++ iounmap(hcd->regs);
++ iounmap(omap->tll_base);
++ iounmap(omap->uhh_base);
++ usb_put_hcd(hcd);
++
++ return 0;
++}
++
++static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
++{
++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
++
++ if (hcd->driver->shutdown)
++ hcd->driver->shutdown(hcd);
++}
++
++static struct platform_driver ehci_hcd_omap_driver = {
++ .probe = ehci_hcd_omap_probe,
++ .remove = ehci_hcd_omap_remove,
++ .shutdown = ehci_hcd_omap_shutdown,
++ /*.suspend = ehci_hcd_omap_suspend, */
++ /*.resume = ehci_hcd_omap_resume, */
++ .driver = {
++ .name = "ehci-omap",
++ }
++};
++
++/*-------------------------------------------------------------------------*/
++
++static const struct hc_driver ehci_omap_hc_driver = {
++ .description = hcd_name,
++ .product_desc = "OMAP-EHCI Host Controller",
++ .hcd_priv_size = sizeof(struct ehci_hcd),
++
++ /*
++ * generic hardware linkage
++ */
++ .irq = ehci_irq,
++ .flags = HCD_MEMORY | HCD_USB2,
++
++ /*
++ * basic lifecycle operations
++ */
++ .reset = ehci_init,
++ .start = ehci_run,
++ .stop = ehci_stop,
++ .shutdown = ehci_shutdown,
++
++ /*
++ * managing i/o requests and associated device resources
++ */
++ .urb_enqueue = ehci_urb_enqueue,
++ .urb_dequeue = ehci_urb_dequeue,
++ .endpoint_disable = ehci_endpoint_disable,
++ .endpoint_reset = ehci_endpoint_reset,
++
++ /*
++ * scheduling support
++ */
++ .get_frame_number = ehci_get_frame,
++
++ /*
++ * root hub support
++ */
++ .hub_status_data = ehci_hub_status_data,
++ .hub_control = ehci_hub_control,
++ .bus_suspend = ehci_bus_suspend,
++ .bus_resume = ehci_bus_resume,
++
++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
++};
++
++MODULE_ALIAS("platform:omap-ehci");
++MODULE_AUTHOR("Texas Instruments, Inc.");
++MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
++
diff --git a/usb/usb-improved-error-handling-in-usb_port_suspend.patch b/usb/usb-improved-error-handling-in-usb_port_suspend.patch
new file mode 100644
index 00000000000000..8bc2d3b0263e5c
--- /dev/null
+++ b/usb/usb-improved-error-handling-in-usb_port_suspend.patch
@@ -0,0 +1,48 @@
+From oliver@neukum.org Tue Oct 27 10:24:50 2009
+From: Oliver Neukum <oliver@neukum.org>
+Date: Mon, 19 Oct 2009 13:19:41 +0200
+Subject: USB: improved error handling in usb_port_suspend()
+To: Greg KH <greg@kroah.com>, Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org
+Message-ID: <200910191319.41745.oliver@neukum.org>
+
+
+usb: better error handling in usb_port_suspend
+
+- disable remote wakeup only if it was enabled
+- refuse to autosuspend if remote wakeup fails to be enabled
+
+Signed-off-by: Oliver Neukum <oliver@neukum.org>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2123,9 +2123,13 @@ int usb_port_suspend(struct usb_device *
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+- if (status)
++ if (status) {
+ dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+ status);
++ /* bail if autosuspend is requested */
++ if (msg.event & PM_EVENT_AUTO)
++ return status;
++ }
+ }
+
+ /* see 7.1.7.6 */
+@@ -2134,7 +2138,8 @@ int usb_port_suspend(struct usb_device *
+ dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ port1, status);
+ /* paranoia: "should not happen" */
+- (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++ if (udev->do_remote_wakeup)
++ (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
diff --git a/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch b/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch
new file mode 100644
index 00000000000000..649fa44866392b
--- /dev/null
+++ b/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch
@@ -0,0 +1,217 @@
+From ext-heikki.krogerus@nokia.com Tue Oct 27 10:09:38 2009
+From: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Date: Thu, 15 Oct 2009 17:09:35 +0300
+Subject: USB OTG: Add generic driver for ULPI OTG transceiver
+To: krohei@gmail.com
+Cc: ext Daniel Mack <daniel@caiaq.de>, Greg Kroah-Hartman <gregkh@suse.de>, David Brownell <dbrownell@users.sourceforge.net>, Sascha Hauer <s.hauer@pengutronix.de>, linux-usb@vger.kernel.org
+Message-ID: <1255615776-17460-3-git-send-email-ext-heikki.krogerus@nokia.com>
+
+
+From: Daniel Mack <daniel@caiaq.de>
+
+This adds a minimal generic driver for ULPI connected transceivers,
+using the OTG framework functions recently introduced.
+
+The driver got a table to match the ULPI chips, which currently only has
+one entry for NXP's ISP 1504 transceiver.
+
+Signed-off-by: Daniel Mack <daniel@caiaq.de>
+Cc: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Cc: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/Makefile | 2
+ drivers/usb/otg/Kconfig | 9 +++
+ drivers/usb/otg/Makefile | 1
+ drivers/usb/otg/ulpi.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/usb/ulpi.h | 7 ++
+ 5 files changed, 155 insertions(+)
+ create mode 100644 drivers/usb/otg/ulpi.c
+ create mode 100644 include/linux/usb/ulpi.h
+
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -44,3 +44,5 @@ obj-y += early/
+
+ obj-$(CONFIG_USB_ATM) += atm/
+ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
++
++obj-$(CONFIG_USB_ULPI) += otg/
+--- a/drivers/usb/otg/Kconfig
++++ b/drivers/usb/otg/Kconfig
+@@ -41,6 +41,15 @@ config ISP1301_OMAP
+ This driver can also be built as a module. If so, the module
+ will be called isp1301_omap.
+
++config USB_ULPI
++ bool "Generic ULPI Transceiver Driver"
++ depends on ARM
++ help
++ Enable this to support ULPI connected USB OTG transceivers which
++ are likely found on embedded boards.
++
++ The only chip currently supported is NXP's ISP1504
++
+ config TWL4030_USB
+ tristate "TWL4030 USB Transceiver Driver"
+ depends on TWL4030_CORE && REGULATOR_TWL4030
+--- a/drivers/usb/otg/Makefile
++++ b/drivers/usb/otg/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus
+ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
+ obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
+ obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
++obj-$(CONFIG_USB_ULPI) += ulpi.o
+
+ ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
+ ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
+--- /dev/null
++++ b/drivers/usb/otg/ulpi.c
+@@ -0,0 +1,136 @@
++/*
++ * Generic ULPI USB transceiver support
++ *
++ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
++ *
++ * Based on sources from
++ *
++ * Sascha Hauer <s.hauer@pengutronix.de>
++ * Freescale Semiconductors
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/usb.h>
++#include <linux/usb/otg.h>
++#include <linux/usb/ulpi.h>
++
++/* ULPI register addresses */
++#define ULPI_VID_LOW 0x00 /* Vendor ID low */
++#define ULPI_VID_HIGH 0x01 /* Vendor ID high */
++#define ULPI_PID_LOW 0x02 /* Product ID low */
++#define ULPI_PID_HIGH 0x03 /* Product ID high */
++#define ULPI_ITFCTL 0x07 /* Interface Control */
++#define ULPI_OTGCTL 0x0A /* OTG Control */
++
++/* add to above register address to access Set/Clear functions */
++#define ULPI_REG_SET 0x01
++#define ULPI_REG_CLEAR 0x02
++
++/* ULPI OTG Control Register bits */
++#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */
++#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */
++#define DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */
++#define DISCHRG_VBUS (1 << 3) /* Discharge Vbus */
++#define CHRG_VBUS (1 << 4) /* Charge Vbus */
++#define DRV_VBUS (1 << 5) /* Drive Vbus */
++#define DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */
++#define USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */
++
++#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
++
++#define TR_FLAG(flags, a, b) (((flags) & a) ? b : 0)
++
++/* ULPI hardcoded IDs, used for probing */
++static unsigned int ulpi_ids[] = {
++ ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */
++};
++
++static int ulpi_set_flags(struct otg_transceiver *otg)
++{
++ unsigned int flags = 0;
++
++ if (otg->flags & USB_OTG_PULLUP_ID)
++ flags |= ID_PULL_UP;
++
++ if (otg->flags & USB_OTG_PULLDOWN_DM)
++ flags |= DM_PULL_DOWN;
++
++ if (otg->flags & USB_OTG_PULLDOWN_DP)
++ flags |= DP_PULL_DOWN;
++
++ if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR)
++ flags |= USE_EXT_VBUS_IND;
++
++ return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
++}
++
++static int ulpi_init(struct otg_transceiver *otg)
++{
++ int i, vid, pid;
++
++ vid = (otg_io_read(otg, ULPI_VID_HIGH) << 8) |
++ otg_io_read(otg, ULPI_VID_LOW);
++ pid = (otg_io_read(otg, ULPI_PID_HIGH) << 8) |
++ otg_io_read(otg, ULPI_PID_LOW);
++
++ pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
++
++ for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
++ if (ulpi_ids[i] == ULPI_ID(vid, pid))
++ return ulpi_set_flags(otg);
++
++ pr_err("ULPI ID does not match any known transceiver.\n");
++ return -ENODEV;
++}
++
++static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
++{
++ unsigned int flags = otg_io_read(otg, ULPI_OTGCTL);
++
++ flags &= ~(DRV_VBUS | DRV_VBUS_EXT);
++
++ if (on) {
++ if (otg->flags & USB_OTG_DRV_VBUS)
++ flags |= DRV_VBUS;
++
++ if (otg->flags & USB_OTG_DRV_VBUS_EXT)
++ flags |= DRV_VBUS_EXT;
++ }
++
++ return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
++}
++
++struct otg_transceiver *
++otg_ulpi_create(struct otg_io_access_ops *ops,
++ unsigned int flags)
++{
++ struct otg_transceiver *otg;
++
++ otg = kzalloc(sizeof(*otg), GFP_KERNEL);
++ if (!otg)
++ return NULL;
++
++ otg->label = "ULPI";
++ otg->flags = flags;
++ otg->io_ops = ops;
++ otg->init = ulpi_init;
++ otg->set_vbus = ulpi_set_vbus;
++
++ return otg;
++}
++EXPORT_SYMBOL_GPL(otg_ulpi_create);
++
+--- /dev/null
++++ b/include/linux/usb/ulpi.h
+@@ -0,0 +1,7 @@
++#ifndef __LINUX_USB_ULPI_H
++#define __LINUX_USB_ULPI_H
++
++struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops,
++ unsigned int flags);
++
++#endif /* __LINUX_USB_ULPI_H */
diff --git a/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch b/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch
new file mode 100644
index 00000000000000..924b806fbc43f5
--- /dev/null
+++ b/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch
@@ -0,0 +1,154 @@
+From ext-heikki.krogerus@nokia.com Tue Oct 27 10:08:40 2009
+From: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Date: Thu, 15 Oct 2009 17:09:34 +0300
+Subject: USB OTG: add support for ulpi connected external transceivers
+To: krohei@gmail.com
+Cc: ext Daniel Mack <daniel@caiaq.de>, Greg Kroah-Hartman <gregkh@suse.de>, David Brownell <dbrownell@users.sourceforge.net>, linux-usb@vger.kernel.org
+Message-ID: <1255615776-17460-2-git-send-email-ext-heikki.krogerus@nokia.com>
+
+
+From: Daniel Mack <daniel@caiaq.de>
+
+This adds support for OTG transceivers directly connected to the ULPI
+interface. In particular, the following details are added
+
+- a struct for low level io functions (read/write)
+- a priv field to be used as 'viewport' by low level access functions
+- an (*init) and (*shutdown) callbacks, along with static inline helpers
+- a (*set_vbus) callback to switch the port power on and off
+- a flags field for per-transceiver settings
+- some defines for the flags bitmask to configure platform specific
+ details
+
+Signed-off-by: Daniel Mack <daniel@caiaq.de>
+Cc: Heikki Krogerus <ext-heikki.krogerus@nokia.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/usb/otg.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 67 insertions(+), 1 deletion(-)
+
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -33,6 +33,23 @@ enum usb_otg_state {
+ OTG_STATE_A_VBUS_ERR,
+ };
+
++#define USB_OTG_PULLUP_ID (1 << 0)
++#define USB_OTG_PULLDOWN_DP (1 << 1)
++#define USB_OTG_PULLDOWN_DM (1 << 2)
++#define USB_OTG_EXT_VBUS_INDICATOR (1 << 3)
++#define USB_OTG_DRV_VBUS (1 << 4)
++#define USB_OTG_DRV_VBUS_EXT (1 << 5)
++
++struct otg_transceiver;
++
++/* for transceivers connected thru an ULPI interface, the user must
++ * provide access ops
++ */
++struct otg_io_access_ops {
++ int (*read)(struct otg_transceiver *otg, u32 reg);
++ int (*write)(struct otg_transceiver *otg, u32 val, u32 reg);
++};
++
+ /*
+ * the otg driver needs to interact with both device side and host side
+ * usb controllers. it decides which controller is active at a given
+@@ -42,6 +59,7 @@ enum usb_otg_state {
+ struct otg_transceiver {
+ struct device *dev;
+ const char *label;
++ unsigned int flags;
+
+ u8 default_a;
+ enum usb_otg_state state;
+@@ -49,10 +67,17 @@ struct otg_transceiver {
+ struct usb_bus *host;
+ struct usb_gadget *gadget;
+
++ struct otg_io_access_ops *io_ops;
++ void __iomem *io_priv;
++
+ /* to pass extra port status to the root hub */
+ u16 port_status;
+ u16 port_change;
+
++ /* initialize/shutdown the OTG controller */
++ int (*init)(struct otg_transceiver *otg);
++ void (*shutdown)(struct otg_transceiver *otg);
++
+ /* bind/unbind the host controller */
+ int (*set_host)(struct otg_transceiver *otg,
+ struct usb_bus *host);
+@@ -65,6 +90,10 @@ struct otg_transceiver {
+ int (*set_power)(struct otg_transceiver *otg,
+ unsigned mA);
+
++ /* effective for A-peripheral, ignored for B devices */
++ int (*set_vbus)(struct otg_transceiver *otg,
++ bool enabled);
++
+ /* for non-OTG B devices: set transceiver into suspend mode */
+ int (*set_suspend)(struct otg_transceiver *otg,
+ int suspend);
+@@ -85,6 +114,38 @@ extern int otg_set_transceiver(struct ot
+ extern void usb_nop_xceiv_register(void);
+ extern void usb_nop_xceiv_unregister(void);
+
++/* helpers for direct access thru low-level io interface */
++static inline int otg_io_read(struct otg_transceiver *otg, u32 reg)
++{
++ if (otg->io_ops && otg->io_ops->read)
++ return otg->io_ops->read(otg, reg);
++
++ return -EINVAL;
++}
++
++static inline int otg_io_write(struct otg_transceiver *otg, u32 reg, u32 val)
++{
++ if (otg->io_ops && otg->io_ops->write)
++ return otg->io_ops->write(otg, reg, val);
++
++ return -EINVAL;
++}
++
++static inline int
++otg_init(struct otg_transceiver *otg)
++{
++ if (otg->init)
++ return otg->init(otg);
++
++ return 0;
++}
++
++static inline void
++otg_shutdown(struct otg_transceiver *otg)
++{
++ if (otg->shutdown)
++ otg->shutdown(otg);
++}
+
+ /* for usb host and peripheral controller drivers */
+ extern struct otg_transceiver *otg_get_transceiver(void);
+@@ -97,6 +158,12 @@ otg_start_hnp(struct otg_transceiver *ot
+ return otg->start_hnp(otg);
+ }
+
++/* Context: can sleep */
++static inline int
++otg_set_vbus(struct otg_transceiver *otg, bool enabled)
++{
++ return otg->set_vbus(otg, enabled);
++}
+
+ /* for HCDs */
+ static inline int
+@@ -105,7 +172,6 @@ otg_set_host(struct otg_transceiver *otg
+ return otg->set_host(otg, host);
+ }
+
+-
+ /* for usb peripheral controller drivers */
+
+ /* Context: can sleep */