aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-07-22 16:57:38 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-07-22 16:57:38 -0700
commit6bbbb136e761db39158852c9b42619c2438e9d45 (patch)
tree4b48eba7be3ba0e7ffbddc0fee4988d26623099a
parent5caca10b163e38f1671c4be83c480581da4d90d6 (diff)
downloadpatches-6bbbb136e761db39158852c9b42619c2438e9d45.tar.gz
lots of patches
-rw-r--r--cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch54
-rw-r--r--series52
-rw-r--r--tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch50
-rw-r--r--tty/serial-altera_uart-simplify-altera_uart_console_putc-checkpatch-fixes.patch47
-rw-r--r--tty/serial-crisv10-formatting-of-pointers-in-printk.patch33
-rw-r--r--tty/serial-fix-missing-bit-coverage-of-async_flags.patch52
-rw-r--r--tty/serial-general-fixes-in-the-serial_rs485-structure.patch83
-rw-r--r--tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch133
-rw-r--r--tty/serial-mmio32-support-for-8250_early.c.patch154
-rw-r--r--tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch50
-rw-r--r--tty/u6715-8250-serial-like-driver.patch340
-rw-r--r--usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch261
-rw-r--r--usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch503
-rw-r--r--usb/usb-delay-init-quirk-for-logitech-harmony-700-series-devices.patch76
-rw-r--r--usb/usb-ehci-add-missing-frame-microframe-conversion.patch98
-rw-r--r--usb/usb-ehci-remove-dead-code-in-the-periodic-scheduler.patch108
-rw-r--r--usb/usb-ehci-remove-pci-assumption.patch78
-rw-r--r--usb/usb-ehci-reorganize-isochronous-scheduler-routine.patch188
-rw-r--r--usb/usb-ehci-simplify-remainder-computations.patch148
-rw-r--r--usb/usb-gadget-functionfs-stale-makefile-entry-removed.patch31
-rw-r--r--usb/usb-gadget-storage-optional-scsi-write-fua-bit.patch217
-rw-r--r--usb/usb-gadget-storage-strict-coversion-of-ro-parameter.patch54
-rw-r--r--usb/usb-host-sl811-hcd-check-kzalloc-result.patch37
-rw-r--r--usb/usb-option-huawei-ets-1220-support-added.patch38
-rw-r--r--usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch198
-rw-r--r--usb/usb-resizing-usbmon-binary-interface-buffer-causes-protection-faults.patch35
-rw-r--r--usb/usb-s3c-hsotg-add-initial-detection-and-setup-for-dedicated-fifo-mode.patch166
-rw-r--r--usb/usb-s3c-hsotg-add-support-for-clock-gating.patch91
-rw-r--r--usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch68
-rw-r--r--usb/usb-s3c-hsotg-avoid-overwriting-contents-of-perodic-in-fifo.patch51
-rw-r--r--usb/usb-s3c-hsotg-check-for-new-request-before-enqueing-new-setup.patch34
-rw-r--r--usb/usb-s3c-hsotg-fix-compilation-problem.patch32
-rw-r--r--usb/usb-s3c-hsotg-fix-max-ep0-in-request-length.patch30
-rw-r--r--usb/usb-s3c-hsotg-fix-out-packet-request-retry.patch89
-rw-r--r--usb/usb-s3c-hsotg-fix-the-out-ep0-limit.patch32
-rw-r--r--usb/usb-s3c-hsotg-increase-tx-fifo-limit.patch45
-rw-r--r--usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch37
-rw-r--r--usb/usb-s3c-hsotg-only-load-packet-per-fifo-write.patch39
-rw-r--r--usb/usb-s3c-hsotg-re-initialise-all-fifos-on-usb-bus-reset.patch44
-rw-r--r--usb/usb-s3c-hsotg-the-nptx-ptx-fifo-sizes-are-in-words-not-bytes.patch43
-rw-r--r--usb/usb-xhci-adds-new-cases-to-trb_comp_code-switch.patch128
-rw-r--r--usb/usb-xhci-allocate-bigger-ring-for-isochronous-endpoint.patch51
-rw-r--r--usb/usb-xhci-handle_tx_event-refactor-finish_td.patch270
-rw-r--r--usb/usb-xhci-handle_tx_event-refactor-process_bulk_intr_td.patch255
-rw-r--r--usb/usb-xhci-handle_tx_event-refactor-process_ctrl_td.patch222
-rw-r--r--usb/usb-xhci-introduce-urb_priv-structure.patch397
-rw-r--r--usb/usb-xhci-isoc-urb-enqueue.patch37
-rw-r--r--usb/usb-xhci-isochronous-transfer-implementation.patch408
-rw-r--r--usb/usb-xhci-missed-service-error-event-process.patch232
-rw-r--r--usb/usb-xhci-remove-redundant-print-messages.patch70
50 files changed, 5986 insertions, 3 deletions
diff --git a/cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch b/cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch
new file mode 100644
index 00000000000000..dc173400cbbb4a
--- /dev/null
+++ b/cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch
@@ -0,0 +1,54 @@
+From: Greg KH <gregkh@suse.de>
+To: Paul Menage <menage@google.com>, Li Zefan <lizf@cn.fujitsu.com>
+Cc: Lennart Poettering <lennart@poettering.net>,
+ Kay Sievers <kay.sievers@vrfy.org>,
+ Andrew Morton <akpm@linux-foundation.org>,
+ KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>,
+ Ben Blum <bblum@andrew.cmu.edu>,
+ containers@lists.linux-foundation.org, linux-kernel@vger.kernel.org
+Subject: cgroupfs: create /sys/fs/cgroup to mount cgroupfs on
+
+We really shouldn't be asking userspace to create new root filesystems.
+So follow along with all of the other in-kernel filesystems, and provide
+a mount point in sysfs.
+
+For cgroupfs, this should be in /sys/fs/cgroup/ This change provides
+that mount point when the cgroup filesystem is registered in the kernel.
+
+Cc: Paul Menage <menage@google.com>
+Cc: Li Zefan <lizf@cn.fujitsu.com>
+Cc: Lennart Poettering <lennart@poettering.net>
+Cc: Kay Sievers <kay.sievers@vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -1623,6 +1623,8 @@ static struct file_system_type cgroup_fs_type = {
+ .kill_sb = cgroup_kill_sb,
+ };
+
++static struct kobject *cgroup_kobj;
++
+ static inline struct cgroup *__d_cgrp(struct dentry *dentry)
+ {
+ return dentry->d_fsdata;
+@@ -3871,9 +3873,18 @@ int __init cgroup_init(void)
+ hhead = css_set_hash(init_css_set.subsys);
+ hlist_add_head(&init_css_set.hlist, hhead);
+ BUG_ON(!init_root_id(&rootnode));
++
++ cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
++ if (!cgroup_kobj) {
++ err = -ENOMEM;
++ goto out;
++ }
++
+ err = register_filesystem(&cgroup_fs_type);
+- if (err < 0)
++ if (err < 0) {
++ kobject_put(cgroup_kobj);
+ goto out;
++ }
+
+ proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
+
diff --git a/series b/series
index 3f212d089eb180..ce218680b6775c 100644
--- a/series
+++ b/series
@@ -128,6 +128,15 @@ tty/serial-max3107-introduce-a-max3107-driver.patch
tty/serial-max3107-abstract-out-the-platform-specific-bits.patch
tty/tty_io-remove-casts-from-void.patch
tty/vt-fix-warning-statement-with-no-effect-due-to-vt_kern.h.patch
+tty/serial-crisv10-formatting-of-pointers-in-printk.patch
+tty/u6715-8250-serial-like-driver.patch
+tty/serial-altera_uart-simplify-altera_uart_console_putc-checkpatch-fixes.patch
+tty/serial-fix-missing-bit-coverage-of-async_flags.patch
+tty/serial-general-fixes-in-the-serial_rs485-structure.patch
+tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
+tty/serial-mmio32-support-for-8250_early.c.patch
+tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch
+tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch
###################################
@@ -221,9 +230,46 @@ usb/usb-otg-ulpi-remove-unused-macro.patch
usb/usb-otg-ulpi-add-support-for-smsc-usb3319-ulpi-phy.patch
usb/usb-otg-ulpi-extend-the-generic-ulpi-driver.patch
usb/usb-xhci-supporting-msi-msi-x.patch
-
-# staging stuff is now in the staging-next tree on git.kernel.org
-
+usb/usb-ehci-remove-pci-assumption.patch
+usb/usb-ehci-simplify-remainder-computations.patch
+usb/usb-ehci-add-missing-frame-microframe-conversion.patch
+usb/usb-ehci-reorganize-isochronous-scheduler-routine.patch
+usb/usb-ehci-remove-dead-code-in-the-periodic-scheduler.patch
+usb/usb-gadget-functionfs-stale-makefile-entry-removed.patch
+usb/usb-resizing-usbmon-binary-interface-buffer-causes-protection-faults.patch
+usb/usb-delay-init-quirk-for-logitech-harmony-700-series-devices.patch
+usb/usb-option-huawei-ets-1220-support-added.patch
+usb/usb-xhci-handle_tx_event-refactor-finish_td.patch
+usb/usb-xhci-handle_tx_event-refactor-process_ctrl_td.patch
+usb/usb-xhci-handle_tx_event-refactor-process_bulk_intr_td.patch
+usb/usb-xhci-remove-redundant-print-messages.patch
+usb/usb-xhci-adds-new-cases-to-trb_comp_code-switch.patch
+usb/usb-xhci-missed-service-error-event-process.patch
+usb/usb-xhci-introduce-urb_priv-structure.patch
+usb/usb-xhci-isochronous-transfer-implementation.patch
+usb/usb-xhci-allocate-bigger-ring-for-isochronous-endpoint.patch
+usb/usb-xhci-isoc-urb-enqueue.patch
+usb/usb-gadget-storage-strict-coversion-of-ro-parameter.patch
+usb/usb-gadget-storage-optional-scsi-write-fua-bit.patch
+usb/usb-host-sl811-hcd-check-kzalloc-result.patch
+usb/usb-s3c-hsotg-increase-tx-fifo-limit.patch
+usb/usb-s3c-hsotg-the-nptx-ptx-fifo-sizes-are-in-words-not-bytes.patch
+usb/usb-s3c-hsotg-avoid-overwriting-contents-of-perodic-in-fifo.patch
+usb/usb-s3c-hsotg-re-initialise-all-fifos-on-usb-bus-reset.patch
+usb/usb-s3c-hsotg-add-initial-detection-and-setup-for-dedicated-fifo-mode.patch
+usb/usb-s3c-hsotg-only-load-packet-per-fifo-write.patch
+usb/usb-s3c-hsotg-check-for-new-request-before-enqueing-new-setup.patch
+usb/usb-s3c-hsotg-fix-max-ep0-in-request-length.patch
+usb/usb-s3c-hsotg-fix-the-out-ep0-limit.patch
+usb/usb-s3c-hsotg-fix-out-packet-request-retry.patch
+usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch
+usb/usb-s3c-hsotg-fix-compilation-problem.patch
+usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch
+usb/usb-s3c-hsotg-add-support-for-clock-gating.patch
+usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch
+usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch
+usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch
+# staging stuff is now in the staging-next tree on git.kernel.org
diff --git a/tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch b/tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch
new file mode 100644
index 00000000000000..51005db027d2bc
--- /dev/null
+++ b/tty/serial-68328serial.c-remove-dead-alma_ans-dragonixvz-m68ez328ads.patch
@@ -0,0 +1,50 @@
+From: Christoph Egger <siccegge@cs.fau.de>
+Message-Id: <201007202226.o6KMQsmU021541@imap1.linux-foundation.org>
+Subject: serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS)
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ siccegge@cs.fau.de, gerg@uclinux.org
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:54 -0700
+
+From: Christoph Egger <siccegge@cs.fau.de>
+
+(ALMA_ANS | DRAGONIXVZ | M68EZ328ADS) doesn't exist in Kconfig, therefore
+remove all references to it from the source code.
+
+Signed-off-by: Christoph Egger <siccegge@cs.fau.de>
+Acked-by: Greg Ungerer <gerg@uclinux.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/68328serial.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+--- a/drivers/serial/68328serial.c
++++ b/drivers/serial/68328serial.c
+@@ -98,19 +98,13 @@ static void change_speed(struct m68k_ser
+ * Setup for console. Argument comes from the boot command line.
+ */
+
+-#if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ)
+-#define CONSOLE_BAUD_RATE 115200
+-#define DEFAULT_CBAUD B115200
+-#else
+- /* (es) */
+- /* note: this is messy, but it works, again, perhaps defined somewhere else?*/
+- #ifdef CONFIG_M68VZ328
+- #define CONSOLE_BAUD_RATE 19200
+- #define DEFAULT_CBAUD B19200
+- #endif
+- /* (/es) */
++/* note: this is messy, but it works, again, perhaps defined somewhere else?*/
++#ifdef CONFIG_M68VZ328
++#define CONSOLE_BAUD_RATE 19200
++#define DEFAULT_CBAUD B19200
+ #endif
+
++
+ #ifndef CONSOLE_BAUD_RATE
+ #define CONSOLE_BAUD_RATE 9600
+ #define DEFAULT_CBAUD B9600
diff --git a/tty/serial-altera_uart-simplify-altera_uart_console_putc-checkpatch-fixes.patch b/tty/serial-altera_uart-simplify-altera_uart_console_putc-checkpatch-fixes.patch
new file mode 100644
index 00000000000000..846ab53462ce74
--- /dev/null
+++ b/tty/serial-altera_uart-simplify-altera_uart_console_putc-checkpatch-fixes.patch
@@ -0,0 +1,47 @@
+From akpm@linux-foundation.org Thu Jul 22 15:54:30 2010
+Message-Id: <201007202226.o6KMQAWX021501@imap1.linux-foundation.org>
+Subject: serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ tklauser@distanz.ch
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:10 -0700
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+ERROR: code indent should use tabs where possible
+#32: FILE: drivers/serial/altera_uart.c:397:
++^I ALTERA_UART_STATUS_TRDY_MSK))$
+
+total: 1 errors, 0 warnings, 39 lines checked
+
+./patches/altera_uart-simplify-altera_uart_console_putc.patch has style problems, please review. If any of these errors
+are false positives report them to the maintainer, see
+CHECKPATCH in MAINTAINERS.
+
+Please run checkpatch prior to sending patches
+
+
+This fix got lost when someone merged "altera_uart: simplify
+altera_uart_console_putc()". Please don't lose fixes. Please don't write
+of mere patches which have trivial checkpatch errors.
+
+Cc: Tobias Klauser <tklauser@distanz.ch>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/altera_uart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/serial/altera_uart.c
++++ b/drivers/serial/altera_uart.c
+@@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struc
+ static void altera_uart_console_putc(struct uart_port *port, const char c)
+ {
+ while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
+- ALTERA_UART_STATUS_TRDY_MSK))
++ ALTERA_UART_STATUS_TRDY_MSK))
+ cpu_relax();
+
+ writel(c, port->membase + ALTERA_UART_TXDATA_REG);
diff --git a/tty/serial-crisv10-formatting-of-pointers-in-printk.patch b/tty/serial-crisv10-formatting-of-pointers-in-printk.patch
new file mode 100644
index 00000000000000..39b33064f9d73b
--- /dev/null
+++ b/tty/serial-crisv10-formatting-of-pointers-in-printk.patch
@@ -0,0 +1,33 @@
+From segooon@gmail.com Thu Jul 22 15:52:47 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+To: kernel-janitors@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@suse.de>,
+ Arnd Bergmann <arnd@arndb.de>,
+ Jesper Nilsson <jesper.nilsson@axis.com>,
+ Ingo Molnar <mingo@elte.hu>, linux-kernel@vger.kernel.org
+Subject: serial: crisv10: formatting of pointers in printk()
+Date: Wed, 14 Jul 2010 22:04:42 +0400
+Message-Id: <1279130682-13704-1-git-send-email-segooon@gmail.com>
+
+Use %p instead of %08x in printk().
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/crisv10.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/serial/crisv10.c
++++ b/drivers/serial/crisv10.c
+@@ -4522,8 +4522,8 @@ static int __init rs_init(void)
+ INIT_WORK(&info->work, do_softint);
+
+ if (info->enabled) {
+- printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
+- serial_driver->name, info->line, (unsigned int)info->ioport);
++ printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
++ serial_driver->name, info->line, info->ioport);
+ }
+ }
+ #ifdef CONFIG_ETRAX_FAST_TIMER
diff --git a/tty/serial-fix-missing-bit-coverage-of-async_flags.patch b/tty/serial-fix-missing-bit-coverage-of-async_flags.patch
new file mode 100644
index 00000000000000..37606cd57df538
--- /dev/null
+++ b/tty/serial-fix-missing-bit-coverage-of-async_flags.patch
@@ -0,0 +1,52 @@
+From akpm@linux-foundation.org Thu Jul 22 15:55:03 2010
+Message-Id: <201007202226.o6KMQkLd021523@imap1.linux-foundation.org>
+Subject: serial: fix missing bit coverage of ASYNC_FLAGS
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ jvillalo@redhat.com, alan@lxorguk.ukuu.org.uk,
+ john.l.villalovos@intel.com
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:46 -0700
+
+From: John Villalovos <jvillalo@redhat.com>
+
+It seems that currently ASYNC_FLAGS is one bit short of covering all the
+bits of the ASYNC user flags. In particular it does not cover the
+ASYNC_AUTOPROBE bit.
+
+ASYNCB_LAST_USER and ASYNCB_AUTOPROBE are both equal to 15.
+
+Therefore:
+ASYNC_AUTOPROBE = 1000 0000 0000 0000
+ASYNC_FLAGS = 0111 1111 1111 1111
+
+So ASYNC_FLAGS is not covering the ASYNC_AUTOPROBE bit.
+
+This patch fixes the issue and with the patch the values will be:
+ASYNC_AUTOPROBE = 1000 0000 0000 0000
+ASYNC_FLAGS = 1111 1111 1111 1111
+
+As a side note, doing a "git grep" I didn't find any use of
+ASYNC_AUTOPROBE or ASYNCB_AUTOPROBE in the kernel, besides this include
+file.
+
+Signed-off-by: John Villalovos <john.l.villalovos@intel.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/serial.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/include/linux/serial.h
++++ b/include/linux/serial.h
+@@ -151,7 +151,7 @@ struct serial_uart_config {
+ #define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)
+ #define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE)
+
+-#define ASYNC_FLAGS ((1U << ASYNCB_LAST_USER) - 1)
++#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1)
+ #define ASYNC_USR_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI| \
+ ASYNC_CALLOUT_NOHUP|ASYNC_SPD_SHI|ASYNC_LOW_LATENCY)
+ #define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
diff --git a/tty/serial-general-fixes-in-the-serial_rs485-structure.patch b/tty/serial-general-fixes-in-the-serial_rs485-structure.patch
new file mode 100644
index 00000000000000..667d3d66f4baac
--- /dev/null
+++ b/tty/serial-general-fixes-in-the-serial_rs485-structure.patch
@@ -0,0 +1,83 @@
+From akpm@linux-foundation.org Thu Jul 22 15:55:22 2010
+Message-Id: <201007202226.o6KMQl2n021527@imap1.linux-foundation.org>
+Subject: serial: general fixes in the serial_rs485 structure
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ claudio@evidence.eu.com, alan@lxorguk.ukuu.org.uk, br@pwrnet.de,
+ phdm@macqel.be
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:47 -0700
+
+From: Claudio Scordino <claudio@evidence.eu.com>
+
+Fix several issues related to the RS485 interface:
+
+ - It adds the flag SER_RS485_RTS_BEFORE_SEND that was missing from the
+ serial_rs485 structure (even if "delay_rts_before_send" was existing)
+
+ - It adds a further "delay_rts_after_send" field for those drivers that
+ can have a delay after send (e.g., atmel_serial)
+
+ - It fixes the usage of the structure in the atmel_serial driver (where
+ "delay_rts_before_send" should be used instead of "delay_rts_after_send").
+
+Signed-off-by: Claudio Scordino <claudio@evidence.eu.com>
+Signed-off-by: Bernhard Roth <br@pwrnet.de>
+Cc: Philippe De Muyter <phdm@macqel.be>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/atmel_serial.c | 11 ++++++++---
+ include/linux/serial.h | 4 +++-
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/serial/atmel_serial.c
++++ b/drivers/serial/atmel_serial.c
+@@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port
+ if (rs485conf->flags & SER_RS485_ENABLED) {
+ dev_dbg(port->dev, "Setting UART to RS485\n");
+ atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
+- UART_PUT_TTGR(port, rs485conf->delay_rts_before_send);
++ if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
++ UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+ mode |= ATMEL_US_USMODE_RS485;
+ } else {
+ dev_dbg(port->dev, "Setting UART to RS232\n");
+@@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_
+
+ if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
+ dev_dbg(port->dev, "Setting UART to RS485\n");
+- UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
++ if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
++ UART_PUT_TTGR(port,
++ atmel_port->rs485.delay_rts_after_send);
+ mode |= ATMEL_US_USMODE_RS485;
+ } else {
+ dev_dbg(port->dev, "Setting UART to RS232\n");
+@@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uar
+
+ if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
+ dev_dbg(port->dev, "Setting UART to RS485\n");
+- UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
++ if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
++ UART_PUT_TTGR(port,
++ atmel_port->rs485.delay_rts_after_send);
+ mode |= ATMEL_US_USMODE_RS485;
+ } else {
+ dev_dbg(port->dev, "Setting UART to RS232\n");
+--- a/include/linux/serial.h
++++ b/include/linux/serial.h
+@@ -210,8 +210,10 @@ struct serial_rs485 {
+ #define SER_RS485_ENABLED (1 << 0)
+ #define SER_RS485_RTS_ON_SEND (1 << 1)
+ #define SER_RS485_RTS_AFTER_SEND (1 << 2)
++#define SER_RS485_RTS_BEFORE_SEND (1 << 3)
+ __u32 delay_rts_before_send; /* Milliseconds */
+- __u32 padding[6]; /* Memory is cheap, new structs
++ __u32 delay_rts_after_send; /* Milliseconds */
++ __u32 padding[5]; /* Memory is cheap, new structs
+ are a royal PITA .. */
+ };
+
diff --git a/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch b/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
new file mode 100644
index 00000000000000..4694b7fd29b273
--- /dev/null
+++ b/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
@@ -0,0 +1,133 @@
+From akpm@linux-foundation.org Thu Jul 22 15:55:47 2010
+Message-Id: <201007202226.o6KMQpNm021530@imap1.linux-foundation.org>
+Subject: serial: mcf: don't take spinlocks in already protected functions
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ ygeorgie@gmail.com, alan@lxorguk.ukuu.org.uk, gerg@uclinux.org
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:50 -0700
+
+From: Yury Georgievskiy <ygeorgie@gmail.com>
+
+Don't take the port spinlock in uart functions where the serial core
+already takes care of locking/unlocking them.
+
+The code would actually lock up on architectures where spinlocks are
+implemented.
+
+Also protect calling mcf_rx_chars/mcf_tx_chars in the interrupt handler by
+the port spinlock and use IRQ_RETVAL to return from isr.
+
+[akpm@linux-foundation.org: make irq-handler return value more explicit]
+Signed-off-by: Yury Georgievskiy <ygeorgie@gmail.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Acked-by: Greg Ungerer <gerg@uclinux.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/mcf.c | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+--- a/drivers/serial/mcf.c
++++ b/drivers/serial/mcf.c
+@@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct
+ static unsigned int mcf_get_mctrl(struct uart_port *port)
+ {
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+- unsigned long flags;
+ unsigned int sigs;
+
+- spin_lock_irqsave(&port->lock, flags);
+ sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
+ 0 : TIOCM_CTS;
+ sigs |= (pp->sigs & TIOCM_RTS);
+ sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
+ sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++
+ return sigs;
+ }
+
+@@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct
+ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
+ {
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+- unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
+ pp->sigs = sigs;
+ mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
+ if (sigs & TIOCM_RTS)
+ writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
+ else
+ writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
+- spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ /****************************************************************************/
+@@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_po
+ static void mcf_start_tx(struct uart_port *port)
+ {
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+- unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
+ pp->imr |= MCFUART_UIR_TXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+- spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ /****************************************************************************/
+@@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_por
+ static void mcf_stop_tx(struct uart_port *port)
+ {
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+- unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
+ pp->imr &= ~MCFUART_UIR_TXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+- spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ /****************************************************************************/
+@@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port
+ static void mcf_stop_rx(struct uart_port *port)
+ {
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+- unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
+ pp->imr &= ~MCFUART_UIR_RXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+- spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ /****************************************************************************/
+@@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq
+ struct uart_port *port = data;
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+ unsigned int isr;
++ irqreturn_t ret = IRQ_NONE;
+
+ isr = readb(port->membase + MCFUART_UISR) & pp->imr;
+- if (isr & MCFUART_UIR_RXREADY)
++
++ spin_lock(&port->lock);
++ if (isr & MCFUART_UIR_RXREADY) {
+ mcf_rx_chars(pp);
+- if (isr & MCFUART_UIR_TXREADY)
++ ret = IRQ_HANDLED;
++ }
++ if (isr & MCFUART_UIR_TXREADY) {
+ mcf_tx_chars(pp);
+- return IRQ_HANDLED;
++ ret = IRQ_HANDLED;
++ }
++ spin_unlock(&port->lock);
++
++ return ret;
+ }
+
+ /****************************************************************************/
diff --git a/tty/serial-mmio32-support-for-8250_early.c.patch b/tty/serial-mmio32-support-for-8250_early.c.patch
new file mode 100644
index 00000000000000..541cbe1379c14a
--- /dev/null
+++ b/tty/serial-mmio32-support-for-8250_early.c.patch
@@ -0,0 +1,154 @@
+From akpm@linux-foundation.org Thu Jul 22 15:56:05 2010
+Message-Id: <201007202226.o6KMQpFh021533@imap1.linux-foundation.org>
+Subject: serial: MMIO32 support for 8250_early.c
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ _deepfire@feelingofgreen.ru, kosaki.motohiro@jp.fujitsu.com,
+ randy.dunlap@oracle.com
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:51 -0700
+
+From: Samium Gromoff <_deepfire@feelingofgreen.ru>
+
+Provide MMIO32 support in 8250_early (aka earlycon)
+
+[randy.dunlap@oracle.com: fix printk format warnings]
+[akpm@linux-foundation.org: fix printk args some more]
+Signed-off-by: Samium Gromoff <_deepfire@feelingofgreen.ru>
+Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
+Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/kernel-parameters.txt | 3 +
+ drivers/serial/8250_early.c | 57 ++++++++++++++++++++++++++----------
+ 2 files changed, 45 insertions(+), 15 deletions(-)
+
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -686,8 +686,11 @@ and is between 256 and 4096 characters.
+ earlycon= [KNL] Output early console device and options.
+ uart[8250],io,<addr>[,options]
+ uart[8250],mmio,<addr>[,options]
++ uart[8250],mmio32,<addr>[,options]
+ Start an early, polled-mode console on the 8250/16550
+ UART at the specified I/O port or MMIO address.
++ MMIO inter-register address stride is either 8bit (mmio)
++ or 32bit (mmio32).
+ The options are the same as for ttyS, above.
+
+ earlyprintk= [X86,SH,BLACKFIN]
+--- a/drivers/serial/8250_early.c
++++ b/drivers/serial/8250_early.c
+@@ -19,9 +19,11 @@
+ * The user can specify the device directly, e.g.,
+ * earlycon=uart8250,io,0x3f8,9600n8
+ * earlycon=uart8250,mmio,0xff5e0000,115200n8
++ * earlycon=uart8250,mmio32,0xff5e0000,115200n8
+ * or
+ * console=uart8250,io,0x3f8,9600n8
+ * console=uart8250,mmio,0xff5e0000,115200n8
++ * console=uart8250,mmio32,0xff5e0000,115200n8
+ */
+
+ #include <linux/tty.h>
+@@ -48,18 +50,31 @@ static struct early_serial8250_device ea
+
+ static unsigned int __init serial_in(struct uart_port *port, int offset)
+ {
+- if (port->iotype == UPIO_MEM)
++ switch (port->iotype) {
++ case UPIO_MEM:
+ return readb(port->membase + offset);
+- else
++ case UPIO_MEM32:
++ return readl(port->membase + (offset << 2));
++ case UPIO_PORT:
+ return inb(port->iobase + offset);
++ default:
++ return 0;
++ }
+ }
+
+ static void __init serial_out(struct uart_port *port, int offset, int value)
+ {
+- if (port->iotype == UPIO_MEM)
++ switch (port->iotype) {
++ case UPIO_MEM:
+ writeb(value, port->membase + offset);
+- else
++ break;
++ case UPIO_MEM32:
++ writel(value, port->membase + (offset << 2));
++ break;
++ case UPIO_PORT:
+ outb(value, port->iobase + offset);
++ break;
++ }
+ }
+
+ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+@@ -137,15 +152,21 @@ static int __init parse_options(struct e
+ char *options)
+ {
+ struct uart_port *port = &device->port;
+- int mmio, length;
++ int mmio, mmio32, length;
+
+ if (!options)
+ return -ENODEV;
+
+ port->uartclk = BASE_BAUD * 16;
+- if (!strncmp(options, "mmio,", 5)) {
+- port->iotype = UPIO_MEM;
+- port->mapbase = simple_strtoul(options + 5, &options, 0);
++
++ mmio = !strncmp(options, "mmio,", 5);
++ mmio32 = !strncmp(options, "mmio32,", 7);
++ if (mmio || mmio32) {
++ port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
++ port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
++ &options, 0);
++ if (mmio32)
++ port->regshift = 2;
+ #ifdef CONFIG_FIX_EARLYCON_MEM
+ set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
+ port->mapbase & PAGE_MASK);
+@@ -157,11 +178,10 @@ static int __init parse_options(struct e
+ if (!port->membase) {
+ printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
+ __func__,
+- (unsigned long long)port->mapbase);
++ (unsigned long long) port->mapbase);
+ return -ENOMEM;
+ }
+ #endif
+- mmio = 1;
+ } else if (!strncmp(options, "io,", 3)) {
+ port->iotype = UPIO_PORT;
+ port->iobase = simple_strtoul(options + 3, &options, 0);
+@@ -181,11 +201,18 @@ static int __init parse_options(struct e
+ device->baud);
+ }
+
+- printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n",
+- mmio ? "MMIO" : "I/O port",
+- mmio ? (unsigned long long) port->mapbase
+- : (unsigned long long) port->iobase,
+- device->options);
++ if (mmio || mmio32)
++ printk(KERN_INFO
++ "Early serial console at MMIO%s 0x%llu (options '%s')\n",
++ mmio32 ? "32" : "",
++ (unsigned long long)port->mapbase,
++ device->options);
++ else
++ printk(KERN_INFO
++ "Early serial console at I/O port 0x%lu (options '%s')\n",
++ port->iobase,
++ device->options);
++
+ return 0;
+ }
+
diff --git a/tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch b/tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch
new file mode 100644
index 00000000000000..eb14dfe2e99d3e
--- /dev/null
+++ b/tty/timbuart-use-__devinit-and-__devexit-macros-for-probe-and-remove.patch
@@ -0,0 +1,50 @@
+From: Richard R�jfors <richard.rojfors@pelagicore.com>
+Message-Id: <201007202226.o6KMQrG8021538@imap1.linux-foundation.org>
+Subject: timbuart: use __devinit and __devexit macros for probe and remove
+To: greg@kroah.com
+Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org,
+ richard.rojfors@pelagicore.com
+From: akpm@linux-foundation.org
+Date: Tue, 20 Jul 2010 15:26:53 -0700
+
+From: Richard R�jfors <richard.rojfors@pelagicore.com>
+
+Move the probe and remove functions to the devinit and devexit sections.
+
+Signed-off-by: Richard R�jfors <richard.rojfors@pelagicore.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/timbuart.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/serial/timbuart.c
++++ b/drivers/serial/timbuart.c
+@@ -423,7 +423,7 @@ static struct uart_driver timbuart_drive
+ .nr = 1
+ };
+
+-static int timbuart_probe(struct platform_device *dev)
++static int __devinit timbuart_probe(struct platform_device *dev)
+ {
+ int err, irq;
+ struct timbuart_port *uart;
+@@ -489,7 +489,7 @@ err_mem:
+ return err;
+ }
+
+-static int timbuart_remove(struct platform_device *dev)
++static int __devexit timbuart_remove(struct platform_device *dev)
+ {
+ struct timbuart_port *uart = platform_get_drvdata(dev);
+
+@@ -507,7 +507,7 @@ static struct platform_driver timbuart_p
+ .owner = THIS_MODULE,
+ },
+ .probe = timbuart_probe,
+- .remove = timbuart_remove,
++ .remove = __devexit_p(timbuart_remove),
+ };
+
+ /*--------------------------------------------------------------------------*/
diff --git a/tty/u6715-8250-serial-like-driver.patch b/tty/u6715-8250-serial-like-driver.patch
new file mode 100644
index 00000000000000..a6a45bd69f9ee5
--- /dev/null
+++ b/tty/u6715-8250-serial-like-driver.patch
@@ -0,0 +1,340 @@
+From philippe.langlais@stericsson.com Thu Jul 22 15:53:24 2010
+From: Philippe Langlais <philippe.langlais@stericsson.com>
+To: <linux-kernel@vger.kernel.org>
+Cc: <gregkh@suse.de>, <ludovic.barre@stericsson.com>,
+ Philippe Langlais <philippe.langlais@stericsson.com>
+Subject: U6715 8250 serial like driver
+Date: Mon, 19 Jul 2010 11:27:40 +0200
+Message-ID: <1279531660-16317-1-git-send-email-philippe.langlais@stericsson.com>
+
+UART Features extract from STEricsson U6715 datasheet (arm926 SoC for mobile phone):
+* Fully compatible with industry standard 16C550 and 16C450 from various
+manufacturers
+* RX and TX 64 byte FIFO reduces CPU interrupts
+* Full double buffering
+* Modem control signals include CTS, RTS, (and DSR, DTR on UART1 only)
+* Automatic baud rate selection
+* Manual or automatic RTS/CTS smart hardware flow control
+* Programmable serial characteristics:
+– Baud rate generation (50 to 3.25M baud)
+– 5, 6, 7 or 8-bit characters
+– Even, odd or no-parity bit generation and detection
+– 1, 1.5 or 2 stop bit generation
+* Independent control of transmit, receive, line status, data set interrupts and FIFOs
+* Full status-reporting capabilities
+* Separate DMA signalling for RX and TX
+* Timed interrupt to spread receive interrupt on known duration
+* DMA time-out interrupt to allow detection of end of reception
+* Carkit pulse coding and decoding compliant with USB carkit control interface [40]
+
+This UART IP is auto-detected as a 16550A type
+
+Clock specificities:
+ It's parent clock depend on baud rate.
+ The UART port can be used before u6xxx clock framework initialization
+
+Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 26 ++++++
+ drivers/serial/8250_u6.c | 179 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/serial/Kconfig | 19 ++++
+ drivers/serial/Makefile | 1
+ include/linux/serial_8250.h | 8 +
+ 5 files changed, 232 insertions(+), 1 deletion(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -199,10 +199,16 @@ static const struct serial8250_config ua
+ },
+ [PORT_16550A] = {
+ .name = "16550A",
++#if defined(CONFIG_SERIAL_8250_U6XXX)
++ .fifo_size = 64,
++ .tx_loadsz = 64,
++ .flags = UART_CAP_FIFO | UART_CAP_AFE,
++#else
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
++#endif
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ },
+ [PORT_CIRRUS] = {
+ .name = "Cirrus",
+@@ -2268,6 +2274,13 @@ serial8250_set_termios(struct uart_port
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
++#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
++ baud = uart_get_baud_rate(port, termios, old, 0,
++ CONFIG_SERIAL_8250_CUSTOM_MAX_BAUDRATE);
++ /* Calculate the new uart clock frequency if it is tunable */
++ port->uartclk = serial8250_get_custom_clock(port, baud);
++#endif
++
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
+@@ -2298,6 +2311,13 @@ serial8250_set_termios(struct uart_port
+ up->mcr &= ~UART_MCR_AFE;
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
++#if defined(CONFIG_SERIAL_8250_U6XXX)
++ /**
++ * When AFE is active, let the HW handle the stop/restart TX
++ * upon CTS change. It reacts much quicker than the SW driver.
++ */
++ port->flags &= ~ASYNC_CTS_FLOW;
++#endif
+ }
+
+ /*
+@@ -2383,6 +2403,10 @@ serial8250_set_termios(struct uart_port
+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+ }
+
++#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
++ /* set the new uart clock frequency if it is tunable */
++ serial8250_set_custom_clock(port);
++#endif
+ serial_dl_write(up, quot);
+
+ /*
+--- /dev/null
++++ b/drivers/serial/8250_u6.c
+@@ -0,0 +1,179 @@
++/*
++ * linux/drivers/serial/8250_pnx.c
++ *
++ * Copyright (C) ST-Ericsson SA 2010
++ * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson.
++ * License terms: GNU General Public License (GPL), version 2
++ */
++
++#include <linux/serial_core.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <mach/serial.h>
++#include <mach/hardware.h>
++#include <mach/clock.h>
++
++/* Register description for FDIV_CTRL */
++/* UART FDIV_CTRL Register (8 bits) */
++#define UARTX_FDIV_CTRL_OFFSET 0xC00
++/* UART FDIV_M Register (16 bits) */
++#define UARTX_FDIV_M_OFFSET 0xC04
++/* UART FDIV_N Register (16 bits) */
++#define UARTX_FDIV_N_OFFSET 0xC08
++
++/* Bits definition for register UARTX_FDIV_CTRL */
++#define UARTX_FDIV_ENABLE_SHIFT 7
++#define UARTX_FDIV_ENABLE_FIELD (0xFFFFFFFF - (0x1UL<<UARTX_FDIV_ENABLE_SHIFT))
++#define UARTX_FDIV_ENABLE_OFF (0x0UL<<UARTX_FDIV_ENABLE_SHIFT)
++#define UARTX_FDIV_ENABLE_ON (0x1UL<<UARTX_FDIV_ENABLE_SHIFT)
++#define UARTX_FDIV_ENABLE (0x1UL<<UARTX_FDIV_ENABLE_SHIFT)
++#define UARTX_CLKSEL_SHIFT 0
++#define UARTX_CLKSEL_FIELD (0xFFFFFFFF - (0x3UL<<UARTX_CLKSEL_SHIFT))
++#define UARTX_CLKSEL_PCLK (0x0UL<<UARTX_CLKSEL_SHIFT)
++#define UARTX_CLKSEL_13M (0x1UL<<UARTX_CLKSEL_SHIFT)
++#define UARTX_CLKSEL_26M (0x2UL<<UARTX_CLKSEL_SHIFT)
++#define UARTX_CLKSEL_3 (0x3UL<<UARTX_CLKSEL_SHIFT)
++
++/*
++ * console and pctools has needed to start before serial_init
++ * (with cgu interface)
++ */
++static int uart_enable_clock(struct uart_port *port)
++{
++ u32 v;
++ v = readl(CGU_GATESC1_REG);
++
++ if (port->irq == IRQ_UART1)
++ v |= CGU_UART1EN_1;
++ else if (port->irq == IRQ_UART2)
++ v |= CGU_UART2EN_1;
++
++ writel(v, CGU_GATESC1_REG);
++
++ return 0;
++}
++
++static int uart_disable_clock(struct uart_port *port)
++{
++ u32 v;
++ v = readl(CGU_GATESC1_REG);
++
++ if (port->irq == IRQ_UART1)
++ v &= ~CGU_UART1EN_0;
++ else if (port->irq == IRQ_UART2)
++ v &= ~CGU_UART2EN_0;
++
++ writel(v, CGU_GATESC1_REG);
++
++ return 0;
++}
++
++unsigned int serial8250_enable_clock(struct uart_port *port)
++{
++ struct u6_uart *uart_u6 = port->private_data;
++
++ if (!uart_u6)
++ return uart_enable_clock(port);
++
++ if (IS_ERR(uart_u6->uartClk)) {
++ printk(KERN_WARNING "%s - uart clock failed error:%ld\n",
++ __func__, PTR_ERR(uart_u6->uartClk));
++ return PTR_ERR(uart_u6->uartClk);
++ }
++
++ if (clk_get_usecount(uart_u6->uartClk) == 0)
++ clk_enable(uart_u6->uartClk);
++ return 0;
++}
++
++unsigned int serial8250_disable_clock(struct uart_port *port)
++{
++ struct u6_uart *uart_u6 = port->private_data;
++
++ if (!uart_u6)
++ return uart_disable_clock(port);
++
++ if (IS_ERR(uart_u6->uartClk)) {
++ printk(KERN_WARNING "%s - uart clk error :%ld\n", __func__,
++ PTR_ERR(uart_u6->uartClk));
++ return PTR_ERR(uart_u6->uartClk);
++ }
++ if (clk_get_usecount(uart_u6->uartClk) >= 1)
++ clk_disable(uart_u6->uartClk);
++
++ return 0;
++}
++
++unsigned int serial8250_get_custom_clock(struct uart_port *port,
++ unsigned int baud)
++{
++ switch (baud) {
++ case 3250000:
++ return 52000000;
++ case 2000000:
++ return 32000000;
++ case 1843200:
++ return 29491200;
++ case 921600:
++ return 14745600;
++ default:
++ return 7372800;
++ }
++}
++
++void serial8250_set_custom_clock(struct uart_port *port)
++{
++ u32 fdiv_m = 0x5F37;
++ u32 fdiv_n = 0x3600;
++ u32 fdiv_ctrl = UARTX_FDIV_ENABLE_ON;
++ struct u6_uart *uart_u6 = port->private_data;
++
++ switch (port->uartclk) {
++ case 7372800: /* clk=13MHz */
++ fdiv_ctrl |= UARTX_CLKSEL_13M;
++ break;
++ case 14745600: /* clk=26MHz */
++ fdiv_ctrl |= UARTX_CLKSEL_26M;
++ break;
++ case 29491200: /* clk=pclk */
++ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
++ break;
++ case 32000000: /* clk=pclk */
++ fdiv_n = 0x3A98;
++ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
++ break;
++ case 52000000: /* clk=pclk */
++ fdiv_n = 0x5F37;
++ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
++ break;
++ }
++
++ if (uart_u6 != NULL && !IS_ERR(uart_u6->uartClk)) {
++ /* if cgu interface is ready and u6_serial_init */
++ struct clk *parentClk;
++
++ if (fdiv_ctrl & UARTX_CLKSEL_26M)
++ parentClk = clk_get(NULL, "clk26m_ck");
++ else if (fdiv_ctrl & UARTX_CLKSEL_PCLK)
++ parentClk = clk_get(NULL, "pclk2_ck");
++ else
++ parentClk = clk_get(NULL, "clk13m_ck");
++
++ if (!IS_ERR(parentClk)) {
++ serial8250_disable_clock(port);
++
++ if (clk_set_parent(uart_u6->uartClk, parentClk) != 0)
++ printk(KERN_WARNING "%s: set parent failed\n", __func__);
++
++ serial8250_enable_clock(port);
++ clk_put(parentClk);
++ }
++ }
++
++ writel(fdiv_m, port->membase + UARTX_FDIV_M_OFFSET);
++ writel(fdiv_n, port->membase + UARTX_FDIV_N_OFFSET);
++ writel(fdiv_ctrl, port->membase + UARTX_FDIV_CTRL_OFFSET);
++}
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -163,6 +163,25 @@ config SERIAL_8250_MANY_PORTS
+ say N here to save some memory. You can also say Y if you have an
+ "intelligent" multiport card such as Cyclades, Digiboards, etc.
+
++config SERIAL_8250_U6XXX
++ bool
++ depends on SERIAL_8250_EXTENDED && PLAT_U6XXX
++ default y
++
++config SERIAL_8250_CUSTOM_CLOCK
++ bool "Support serial ports with tunable input clock frequency"
++ depends on SERIAL_8250_EXTENDED && SERIAL_8250_U6XXX
++ default y
++ help
++ Say Y here if your platform has specific registers to change UART clock frequency.
++
++config SERIAL_8250_CUSTOM_MAX_BAUDRATE
++ int "Maximal reachable baudrate"
++ depends on SERIAL_8250_CUSTOM_CLOCK
++ default "3250000"
++ help
++ The value of the maximal reachable baudrate when tuning UART clock frequency (default value: 3.25MBds).
++
+ #
+ # Multi-port serial cards
+ #
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_b
+ obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+ obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
++obj-$(CONFIG_SERIAL_8250_U6XXX) += 8250_u6.o
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -72,4 +72,12 @@ extern int serial8250_find_port(struct u
+ extern int serial8250_find_port_for_earlycon(void);
+ extern int setup_early_serial8250_console(char *cmdline);
+
++#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
++unsigned int serial8250_enable_clock(struct uart_port *port);
++unsigned int serial8250_disable_clock(struct uart_port *port);
++unsigned int serial8250_get_custom_clock(struct uart_port *port,
++ unsigned int baud);
++void serial8250_set_custom_clock(struct uart_port *port);
++#endif
++
+ #endif
diff --git a/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch b/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch
new file mode 100644
index 00000000000000..0f12d9a906c03e
--- /dev/null
+++ b/usb/usb-add-of_platform-glue-driver-for-fsl-usb-dr-controller.patch
@@ -0,0 +1,261 @@
+From agust@denx.de Thu Jul 22 16:54:08 2010
+From: Anatolij Gustschin <agust@denx.de>
+To: linux-usb@vger.kernel.org
+Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>,
+ David Brownell <dbrownell@users.sourceforge.net>,
+ Grant Likely <grant.likely@secretlab.ca>,
+ Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>,
+ Anatolij Gustschin <agust@denx.de>,
+ Kumar Gala <galak@kernel.crashing.org>
+Subject: USB: add of_platform glue driver for FSL USB DR controller
+Date: Thu, 22 Jul 2010 18:25:21 +0200
+Message-Id: <1279815922-27198-3-git-send-email-agust@denx.de>
+
+The driver creates platform devices based on the information
+from USB nodes in the flat device tree. This is the replacement
+for old arch fsl_soc usb code removed by the previous patch.
+It uses usual of-style binding, available EHCI-HCD and UDC
+drivers can be bound to the created devices. The new of-style
+driver additionaly instantiates USB OTG platform device, as the
+appropriate USB OTG driver will be added soon.
+
+Signed-off-by: Anatolij Gustschin <agust@denx.de>
+Cc: Kumar Gala <galak@kernel.crashing.org>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/Kconfig | 1
+ drivers/usb/host/Kconfig | 5 +
+ drivers/usb/host/Makefile | 1
+ drivers/usb/host/fsl-mph-dr-of.c | 189 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 196 insertions(+)
+
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2
+ boolean "Freescale Highspeed USB DR Peripheral Controller"
+ depends on FSL_SOC || ARCH_MXC
+ select USB_GADGET_DUALSPEED
++ select USB_FSL_MPH_DR_OF
+ help
+ Some of Freescale PowerPC processors have a High Speed
+ Dual-Role(DR) USB controller, which supports device mode.
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -112,10 +112,15 @@ config XPS_USB_HCD_XILINX
+ support both high speed and full speed devices, or high speed
+ devices only.
+
++config USB_FSL_MPH_DR_OF
++ bool
++ depends on PPC_OF
++
+ config USB_EHCI_FSL
+ bool "Support for Freescale on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && FSL_SOC
+ select USB_EHCI_ROOT_HUB_TT
++ select USB_FSL_MPH_DR_OF
+ ---help---
+ Variation of ARC USB block used in some Freescale chips.
+
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -33,4 +33,5 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a665
+ obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
+ obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
+ obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
++obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
+
+--- /dev/null
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -0,0 +1,189 @@
++/*
++ * Setup platform devices needed by the Freescale multi-port host
++ * and/or dual-role USB controller modules based on the description
++ * in flat device tree.
++ *
++ * 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/fsl_devices.h>
++#include <linux/io.h>
++#include <linux/of_platform.h>
++
++struct fsl_usb2_dev_data {
++ char *dr_mode; /* controller mode */
++ char *drivers[3]; /* drivers to instantiate for this mode */
++ enum fsl_usb2_operating_modes op_mode; /* operating mode */
++};
++
++struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
++ {
++ "host",
++ { "fsl-ehci", NULL, NULL, },
++ FSL_USB2_DR_HOST,
++ },
++ {
++ "otg",
++ { "fsl-ehci", "fsl-usb2-udc", "fsl-usb2-otg", },
++ FSL_USB2_DR_OTG,
++ },
++ {
++ "periferal",
++ { "fsl-usb2-udc", NULL, NULL, },
++ FSL_USB2_DR_DEVICE,
++ },
++};
++
++struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
++{
++ const unsigned char *prop;
++ int i;
++
++ prop = of_get_property(np, "dr_mode", NULL);
++ if (prop) {
++ for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) {
++ if (!strcmp(prop, dr_mode_data[i].dr_mode))
++ return &dr_mode_data[i];
++ }
++ }
++ return &dr_mode_data[0]; /* mode not specified, use host */
++}
++
++static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
++{
++ if (!phy_type)
++ return FSL_USB2_PHY_NONE;
++ if (!strcasecmp(phy_type, "ulpi"))
++ return FSL_USB2_PHY_ULPI;
++ if (!strcasecmp(phy_type, "utmi"))
++ return FSL_USB2_PHY_UTMI;
++ if (!strcasecmp(phy_type, "utmi_wide"))
++ return FSL_USB2_PHY_UTMI_WIDE;
++ if (!strcasecmp(phy_type, "serial"))
++ return FSL_USB2_PHY_SERIAL;
++
++ return FSL_USB2_PHY_NONE;
++}
++
++struct platform_device * __devinit
++fsl_usb2_device_register(struct of_device *ofdev,
++ struct fsl_usb2_platform_data *pdata,
++ const char *name, int id)
++{
++ struct platform_device *pdev;
++ const struct resource *res = ofdev->resource;
++ unsigned int num = ofdev->num_resources;
++ int retval;
++
++ pdev = platform_device_alloc(name, id);
++ if (!pdev) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
++ pdev->dev.parent = &ofdev->dev;
++
++ pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
++ pdev->dev.dma_mask = &pdev->archdata.dma_mask;
++ *pdev->dev.dma_mask = *ofdev->dev.dma_mask;
++
++ retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
++ if (retval)
++ goto error;
++
++ if (num) {
++ retval = platform_device_add_resources(pdev, res, num);
++ if (retval)
++ goto error;
++ }
++
++ retval = platform_device_add(pdev);
++ if (retval)
++ goto error;
++
++ return pdev;
++
++error:
++ platform_device_put(pdev);
++ return ERR_PTR(retval);
++}
++
++static int __devinit fsl_usb2_mph_dr_of_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct device_node *np = ofdev->dev.of_node;
++ struct platform_device *usb_dev;
++ struct fsl_usb2_platform_data data, *pdata;
++ struct fsl_usb2_dev_data *dev_data;
++ const unsigned char *prop;
++ static unsigned int idx;
++ int i;
++
++ if (!of_device_is_available(np))
++ return -ENODEV;
++
++ pdata = match->data;
++ if (!pdata) {
++ memset(&data, 0, sizeof(data));
++ pdata = &data;
++ }
++
++ dev_data = get_dr_mode_data(np);
++
++ if (of_device_is_compatible(np, "fsl-usb2-mph")) {
++ prop = of_get_property(np, "port0", NULL);
++ if (prop)
++ pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
++
++ prop = of_get_property(np, "port1", NULL);
++ if (prop)
++ pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
++
++ pdata->operating_mode = FSL_USB2_MPH_HOST;
++ } else {
++ /* setup mode selected in the device tree */
++ pdata->operating_mode = dev_data->op_mode;
++ }
++
++ prop = of_get_property(np, "phy_type", NULL);
++ pdata->phy_mode = determine_usb_phy(prop);
++
++ for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
++ if (!dev_data->drivers[i])
++ continue;
++ usb_dev = fsl_usb2_device_register(ofdev, pdata,
++ dev_data->drivers[i], idx);
++ if (IS_ERR(usb_dev)) {
++ dev_err(&ofdev->dev, "Can't register usb device\n");
++ return PTR_ERR(usb_dev);
++ }
++ }
++ idx++;
++ return 0;
++}
++
++static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
++ { .compatible = "fsl-usb2-mph", },
++ { .compatible = "fsl-usb2-dr", },
++ {},
++};
++
++static struct of_platform_driver fsl_usb2_mph_dr_driver = {
++ .driver = {
++ .name = "fsl-usb2-mph-dr",
++ .owner = THIS_MODULE,
++ .of_match_table = fsl_usb2_mph_dr_of_match,
++ },
++ .probe = fsl_usb2_mph_dr_of_probe,
++};
++
++static int __init fsl_usb2_mph_dr_init(void)
++{
++ return of_register_platform_driver(&fsl_usb2_mph_dr_driver);
++}
++fs_initcall(fsl_usb2_mph_dr_init);
diff --git a/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch b/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch
new file mode 100644
index 00000000000000..6fa814f54f40e8
--- /dev/null
+++ b/usb/usb-add-usb-ehci-support-for-mpc5121-soc.patch
@@ -0,0 +1,503 @@
+From agust@denx.de Thu Jul 22 16:54:48 2010
+From: Anatolij Gustschin <agust@denx.de>
+To: linux-usb@vger.kernel.org
+Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>,
+ David Brownell <dbrownell@users.sourceforge.net>,
+ Grant Likely <grant.likely@secretlab.ca>,
+ Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>,
+ Anatolij Gustschin <agust@denx.de>
+Subject: USB: add USB EHCI support for MPC5121 SoC
+Date: Thu, 22 Jul 2010 18:25:22 +0200
+Message-Id: <1279815922-27198-4-git-send-email-agust@denx.de>
+
+Extends FSL EHCI platform driver glue layer to support
+MPC5121 USB controllers. MPC5121 Rev 2.0 silicon EHCI
+registers are in big endian format. The appropriate flags
+are set using the information in the platform data structure.
+MPC83xx system interface registers are not available on
+MPC512x, so the access to these registers is isolated in
+MPC512x case. Furthermore the USB controller clocks
+must be enabled before 512x register accesses which is
+done by providing platform specific init callback.
+
+The MPC512x internal USB PHY doesn't provide supply voltage.
+For boards using different power switches allow specifying
+DRVVBUS and PWR_FAULT signal polarity of the MPC5121 internal
+PHY using "fsl,invert-drvvbus" and "fsl,invert-pwr-fault"
+properties in the device tree USB nodes. Adds documentation
+for this new device tree bindings.
+
+Signed-off-by: Anatolij Gustschin <agust@denx.de>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/powerpc/dts-bindings/fsl/usb.txt | 22 +++++
+ drivers/usb/Kconfig | 1
+ drivers/usb/host/Kconfig | 6 -
+ drivers/usb/host/ehci-fsl.c | 107 ++++++++++++++++++-------
+ drivers/usb/host/ehci-fsl.h | 19 ++++
+ drivers/usb/host/ehci-mem.c | 2
+ drivers/usb/host/fsl-mph-dr-of.c | 89 ++++++++++++++++++++
+ include/linux/fsl_devices.h | 15 +++
+ 8 files changed, 229 insertions(+), 32 deletions(-)
+
+--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
++++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
+@@ -8,6 +8,7 @@ and additions :
+ Required properties :
+ - compatible : Should be "fsl-usb2-mph" for multi port host USB
+ controllers, or "fsl-usb2-dr" for dual role USB controllers
++ or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
+ - phy_type : For multi port host USB controllers, should be one of
+ "ulpi", or "serial". For dual role USB controllers, should be
+ one of "ulpi", "utmi", "utmi_wide", or "serial".
+@@ -33,6 +34,12 @@ Recommended properties :
+ - interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+
++Optional properties :
++ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
++ port power polarity of internal PHY signal DRVVBUS is inverted.
++ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
++ the PWR_FAULT signal polarity is inverted.
++
+ Example multi port host USB controller device node :
+ usb@22000 {
+ compatible = "fsl-usb2-mph";
+@@ -57,3 +64,18 @@ Example dual role USB controller device
+ dr_mode = "otg";
+ phy = "ulpi";
+ };
++
++Example dual role USB controller device node for MPC5121ADS:
++
++ usb@4000 {
++ compatible = "fsl,mpc5121-usb2-dr";
++ reg = <0x4000 0x1000>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ interrupt-parent = < &ipic >;
++ interrupts = <44 0x8>;
++ dr_mode = "otg";
++ phy_type = "utmi_wide";
++ fsl,invert-drvvbus;
++ fsl,invert-pwr-fault;
++ };
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -58,6 +58,7 @@ config USB_ARCH_HAS_OHCI
+ config USB_ARCH_HAS_EHCI
+ boolean
+ default y if PPC_83xx
++ default y if PPC_MPC512x
+ default y if SOC_AU1200
+ default y if ARCH_IXP4XX
+ default y if ARCH_W90X900
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED
+
+ config USB_EHCI_BIG_ENDIAN_MMIO
+ bool
+- depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
++ depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
++ XPS_USB_HCD_XILINX || PPC_MPC512x)
+ default y
+
+ config USB_EHCI_BIG_ENDIAN_DESC
+ bool
+- depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
++ depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
++ PPC_MPC512x)
+ default y
+
+ config XPS_USB_HCD_XILINX
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -116,13 +116,39 @@ static int usb_hcd_fsl_probe(const struc
+ goto err3;
+ }
+
+- /* Enable USB controller */
+- temp = in_be32(hcd->regs + 0x500);
+- out_be32(hcd->regs + 0x500, temp | 0x4);
++ pdata->regs = hcd->regs;
++
++ /*
++ * do platform specific init: check the clock, grab/config pins, etc.
++ */
++ if (pdata->init && pdata->init(pdev)) {
++ retval = -ENODEV;
++ goto err3;
++ }
++
++ /*
++ * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
++ * flag for 83xx or 8536 system interface registers.
++ */
++ if (pdata->big_endian_mmio)
++ temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
++ else
++ temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
++
++ if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
++ pdata->have_sysif_regs = 1;
++
++ /* Enable USB controller, 83xx or 8536 */
++ if (pdata->have_sysif_regs)
++ setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+
+ /* Set to Host mode */
+- temp = in_le32(hcd->regs + 0x1a8);
+- out_le32(hcd->regs + 0x1a8, temp | 0x3);
++ if (pdata->big_endian_mmio) {
++ setbits32(hcd->regs + FSL_SOC_USB_USBMODE, USBMODE_CM_HOST);
++ } else {
++ clrsetbits_le32(hcd->regs + FSL_SOC_USB_USBMODE,
++ USBMODE_CM_MASK, USBMODE_CM_HOST);
++ }
+
+ retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+ if (retval != 0)
+@@ -137,6 +163,8 @@ static int usb_hcd_fsl_probe(const struc
+ usb_put_hcd(hcd);
+ err1:
+ dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
++ if (pdata->exit)
++ pdata->exit(pdev);
+ return retval;
+ }
+
+@@ -154,17 +182,30 @@ static int usb_hcd_fsl_probe(const struc
+ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
+ struct platform_device *pdev)
+ {
++ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
++
+ usb_remove_hcd(hcd);
++
++ /*
++ * do platform specific un-initialization:
++ * release iomux pins, disable clock, etc.
++ */
++ if (pdata->exit)
++ pdata->exit(pdev);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+ }
+
+-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
+- enum fsl_usb2_phy_modes phy_mode,
+- unsigned int port_offset)
++static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
++ enum fsl_usb2_phy_modes phy_mode,
++ unsigned int port_offset)
+ {
+- u32 portsc = 0;
++ u32 portsc;
++
++ portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
++ portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
++
+ switch (phy_mode) {
+ case FSL_USB2_PHY_ULPI:
+ portsc |= PORT_PTS_ULPI;
+@@ -184,20 +225,21 @@ static void mpc83xx_setup_phy(struct ehc
+ ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
+ }
+
+-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
++static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+ {
+- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ struct fsl_usb2_platform_data *pdata;
+ void __iomem *non_ehci = hcd->regs;
+ u32 temp;
+
+- pdata =
+- (struct fsl_usb2_platform_data *)hcd->self.controller->
+- platform_data;
++ pdata = hcd->self.controller->platform_data;
++
+ /* Enable PHY interface in the control reg. */
+- temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+- out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
+- out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
++ if (pdata->have_sysif_regs) {
++ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
++ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
++ out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
++ }
+
+ #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ /*
+@@ -214,7 +256,7 @@ static void mpc83xx_usb_setup(struct usb
+
+ if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+ (pdata->operating_mode == FSL_USB2_DR_OTG))
+- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
++ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
+
+ if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
+ unsigned int chip, rev, svr;
+@@ -228,27 +270,31 @@ static void mpc83xx_usb_setup(struct usb
+ ehci->has_fsl_port_bug = 1;
+
+ if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
+- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
++ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
+ if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
+- mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
++ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
+ }
+
+ /* put controller in host mode. */
+- ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
++ temp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
++ ehci_writel(ehci, temp, non_ehci + FSL_SOC_USB_USBMODE);
++
++ if (pdata->have_sysif_regs) {
+ #ifdef CONFIG_PPC_85xx
+- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
++ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
++ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+ #else
+- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
++ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
++ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+ #endif
+- out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
++ out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
++ }
+ }
+
+ /* called after powerup, by probe or system-pm "wakeup" */
+ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
+ {
+- mpc83xx_usb_setup(ehci_to_hcd(ehci));
++ ehci_fsl_usb_setup(ehci);
+ ehci_port_power(ehci, 0);
+
+ return 0;
+@@ -259,6 +305,11 @@ static int ehci_fsl_setup(struct usb_hcd
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int retval;
++ struct fsl_usb2_platform_data *pdata;
++
++ pdata = hcd->self.controller->platform_data;
++ ehci->big_endian_desc = pdata->big_endian_desc;
++ ehci->big_endian_mmio = pdata->big_endian_mmio;
+
+ /* EHCI registers start at offset 0x100 */
+ ehci->caps = hcd->regs + 0x100;
+@@ -372,7 +423,7 @@ static const struct hc_driver ehci_fsl_h
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+- .flags = HCD_USB2,
++ .flags = HCD_USB2 | HCD_MEMORY,
+
+ /*
+ * basic lifecycle operations
+--- a/drivers/usb/host/ehci-fsl.h
++++ b/drivers/usb/host/ehci-fsl.h
+@@ -1,4 +1,4 @@
+-/* Copyright (c) 2005 freescale semiconductor
++/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -19,6 +19,11 @@
+ #define _EHCI_FSL_H
+
+ /* offsets for the non-ehci registers in the FSL SOC USB controller */
++#define FSL_SOC_USB_ID 0x0
++#define ID_MSK 0x3f
++#define NID_MSK 0x3f00
++#define FSL_SOC_USB_SBUSCFG 0x90
++#define FSL_SOC_USB_BURSTSIZE 0x160
+ #define FSL_SOC_USB_ULPIVP 0x170
+ #define FSL_SOC_USB_PORTSC1 0x184
+ #define PORT_PTS_MSK (3<<30)
+@@ -26,8 +31,20 @@
+ #define PORT_PTS_ULPI (2<<30)
+ #define PORT_PTS_SERIAL (3<<30)
+ #define PORT_PTS_PTW (1<<28)
++#define PORT_PTS_PHCD (1<<23)
+ #define FSL_SOC_USB_PORTSC2 0x188
+ #define FSL_SOC_USB_USBMODE 0x1a8
++#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */
++#define USBMODE_CM_HOST (3 << 0) /* controller mode: host */
++#define USBMODE_ES (1 << 2) /* (Big) Endian Select */
++
++#define FSL_SOC_USB_USBGENCTRL 0x200
++#define USBGENCTRL_PPP (1 << 3)
++#define USBGENCTRL_PFP (1 << 2)
++#define FSL_SOC_USB_ISIPHYCTRL 0x204
++#define ISIPHYCTRL_PXE (1)
++#define ISIPHYCTRL_PHYE (1 << 4)
++
+ #define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */
+ #define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */
+ #define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct
+ {
+ memset (qtd, 0, sizeof *qtd);
+ qtd->qtd_dma = dma;
+- qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
++ qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
+ qtd->hw_next = EHCI_LIST_END(ehci);
+ qtd->hw_alt_next = EHCI_LIST_END(ehci);
+ INIT_LIST_HEAD (&qtd->qtd_list);
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -14,6 +14,7 @@
+ #include <linux/fsl_devices.h>
+ #include <linux/io.h>
+ #include <linux/of_platform.h>
++#include <linux/clk.h>
+
+ struct fsl_usb2_dev_data {
+ char *dr_mode; /* controller mode */
+@@ -146,6 +147,12 @@ static int __devinit fsl_usb2_mph_dr_of_
+
+ pdata->operating_mode = FSL_USB2_MPH_HOST;
+ } else {
++ if (of_get_property(np, "fsl,invert-drvvbus", NULL))
++ pdata->invert_drvvbus = 1;
++
++ if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
++ pdata->invert_pwr_fault = 1;
++
+ /* setup mode selected in the device tree */
+ pdata->operating_mode = dev_data->op_mode;
+ }
+@@ -167,9 +174,91 @@ static int __devinit fsl_usb2_mph_dr_of_
+ return 0;
+ }
+
++#ifdef CONFIG_PPC_MPC512x
++
++#define USBGENCTRL 0x200 /* NOTE: big endian */
++#define GC_WU_INT_CLR (1 << 5) /* Wakeup int clear */
++#define GC_ULPI_SEL (1 << 4) /* ULPI i/f select (usb0 only)*/
++#define GC_PPP (1 << 3) /* Inv. Port Power Polarity */
++#define GC_PFP (1 << 2) /* Inv. Power Fault Polarity */
++#define GC_WU_ULPI_EN (1 << 1) /* Wakeup on ULPI event */
++#define GC_WU_IE (1 << 1) /* Wakeup interrupt enable */
++
++#define ISIPHYCTRL 0x204 /* NOTE: big endian */
++#define PHYCTRL_PHYE (1 << 4) /* On-chip UTMI PHY enable */
++#define PHYCTRL_BSENH (1 << 3) /* Bit Stuff Enable High */
++#define PHYCTRL_BSEN (1 << 2) /* Bit Stuff Enable */
++#define PHYCTRL_LSFE (1 << 1) /* Line State Filter Enable */
++#define PHYCTRL_PXE (1 << 0) /* PHY oscillator enable */
++
++int fsl_usb2_mpc5121_init(struct platform_device *pdev)
++{
++ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
++ struct clk *clk;
++ char clk_name[10];
++ int base, clk_num;
++
++ base = pdev->resource->start & 0xf000;
++ if (base == 0x3000)
++ clk_num = 1;
++ else if (base == 0x4000)
++ clk_num = 2;
++ else
++ return -ENODEV;
++
++ snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
++ clk = clk_get(&pdev->dev, clk_name);
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get clk\n");
++ return PTR_ERR(clk);
++ }
++
++ clk_enable(clk);
++ pdata->clk = clk;
++
++ if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
++ u32 reg = 0;
++
++ if (pdata->invert_drvvbus)
++ reg |= GC_PPP;
++
++ if (pdata->invert_pwr_fault)
++ reg |= GC_PFP;
++
++ out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
++ out_be32(pdata->regs + USBGENCTRL, reg);
++ }
++ return 0;
++}
++
++static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
++{
++ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
++
++ pdata->regs = NULL;
++
++ if (pdata->clk) {
++ clk_disable(pdata->clk);
++ clk_put(pdata->clk);
++ }
++}
++
++struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
++ .big_endian_desc = 1,
++ .big_endian_mmio = 1,
++ .es = 1,
++ .le_setup_buf = 1,
++ .init = fsl_usb2_mpc5121_init,
++ .exit = fsl_usb2_mpc5121_exit,
++};
++#endif /* CONFIG_PPC_MPC512x */
++
+ static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
+ { .compatible = "fsl-usb2-mph", },
+ { .compatible = "fsl-usb2-dr", },
++#ifdef CONFIG_PPC_MPC512x
++ { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
++#endif
+ {},
+ };
+
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -58,11 +58,26 @@ enum fsl_usb2_phy_modes {
+ FSL_USB2_PHY_SERIAL,
+ };
+
++struct clk;
++struct platform_device;
++
+ struct fsl_usb2_platform_data {
+ /* board specific information */
+ enum fsl_usb2_operating_modes operating_mode;
+ enum fsl_usb2_phy_modes phy_mode;
+ unsigned int port_enables;
++
++ int (*init)(struct platform_device *);
++ void (*exit)(struct platform_device *);
++ void __iomem *regs; /* ioremap'd register base */
++ struct clk *clk;
++ unsigned big_endian_mmio:1;
++ unsigned big_endian_desc:1;
++ unsigned es:1; /* need USBMODE:ES */
++ unsigned le_setup_buf:1;
++ unsigned have_sysif_regs:1;
++ unsigned invert_drvvbus:1;
++ unsigned invert_pwr_fault:1;
+ };
+
+ /* Flags in fsl_usb2_mph_platform_data */
diff --git a/usb/usb-delay-init-quirk-for-logitech-harmony-700-series-devices.patch b/usb/usb-delay-init-quirk-for-logitech-harmony-700-series-devices.patch
new file mode 100644
index 00000000000000..699b7c80d8fbb0
--- /dev/null
+++ b/usb/usb-delay-init-quirk-for-logitech-harmony-700-series-devices.patch
@@ -0,0 +1,76 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 15:58:49 2010
+Message-ID: <4C476F0D.1050707@ipom.com>
+Date: Thu, 22 Jul 2010 00:05:01 +0200
+From: Phil Dibowitz <phil@ipom.com>
+To: Greg KH <greg@kroah.com>
+CC: Stephen Warren <swarren@wwwdotorg.org>
+Subject: USB delay init quirk for logitech Harmony 700-series devices
+
+
+The Logitech Harmony 700 series needs an extra delay during
+initialization. This patch adds a USB quirk which enables such a delay
+and adds the device to the quirks list.
+
+Signed-off-by: Phil Dibowitz <phil@ipom.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/core/hub.c | 6 +++++-
+ drivers/usb/core/quirks.c | 3 +++
+ include/linux/usb/quirks.h | 4 ++++
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -20,6 +20,7 @@
+ #include <linux/usb.h>
+ #include <linux/usbdevice_fs.h>
+ #include <linux/usb/hcd.h>
++#include <linux/usb/quirks.h>
+ #include <linux/kthread.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
+@@ -1802,7 +1803,6 @@ int usb_new_device(struct usb_device *ud
+ pm_runtime_set_active(&udev->dev);
+ pm_runtime_enable(&udev->dev);
+
+- usb_detect_quirks(udev);
+ err = usb_enumerate_device(udev); /* Read descriptors */
+ if (err < 0)
+ goto fail;
+@@ -3114,6 +3114,10 @@ static void hub_port_connect_change(stru
+ if (status < 0)
+ goto loop;
+
++ usb_detect_quirks(udev);
++ if (udev->quirks & USB_QUIRK_DELAY_INIT)
++ msleep(1000);
++
+ /* consecutive bus-powered hubs aren't reliable; they can
+ * violate the voltage drop budget. if the new child has
+ * a "powered" LED, users should notice we didn't enable it
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -38,6 +38,9 @@ static const struct usb_device_id usb_qu
+ /* Creative SB Audigy 2 NX */
+ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
+
++ /* Logitech Harmony 700-series */
++ { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
++
+ /* Philips PSC805 audio device */
+ { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -26,4 +26,8 @@
+ and can't handle talking to these interfaces */
+ #define USB_QUIRK_HONOR_BNUMINTERFACES 0x00000020
+
++/* device needs a pause during initialization, after we read the device
++ descriptor */
++#define USB_QUIRK_DELAY_INIT 0x00000040
++
+ #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/usb/usb-ehci-add-missing-frame-microframe-conversion.patch b/usb/usb-ehci-add-missing-frame-microframe-conversion.patch
new file mode 100644
index 00000000000000..aca6f30fd2eb88
--- /dev/null
+++ b/usb/usb-ehci-add-missing-frame-microframe-conversion.patch
@@ -0,0 +1,98 @@
+From stern+4c290172@rowland.harvard.edu Thu Jul 22 15:51:56 2010
+Date: Wed, 14 Jul 2010 11:03:46 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: David Brownell <david-b@pacbell.net>, USB list <linux-usb@vger.kernel.org>
+Subject: USB: EHCI: add missing frame -> microframe conversion
+Message-ID: <Pine.LNX.4.44L0.1007141056230.1634-100000@iolanthe.rowland.org>
+
+This patch (as1407) fixes a bug in ehci-hcd's isochronous scheduler.
+All its calculations should be done in terms of microframes, but for
+full-speed devices, sched->span is stored in frames. It needs to be
+converted.
+
+This fix is liable to expose problems in other drivers. The old code
+would accept URBs that should not have been accepted, so drivers have
+had no reason to avoid submitting URBs that exceeded the maximum
+schedule length. In an attempt to partially compensate for this, the
+patch also adjusts the schedule length from a minimum of 256 frames up
+to a minimum of 512 frames.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: David Brownell <david-b@pacbell.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/host/ehci-hcd.c | 8 +++++++-
+ drivers/usb/host/ehci-sched.c | 21 ++++++++++++---------
+ 2 files changed, 19 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -79,7 +79,13 @@ static const char hcd_name [] = "ehci_hc
+ #define EHCI_TUNE_RL_TT 0
+ #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
+ #define EHCI_TUNE_MULT_TT 1
+-#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
++/*
++ * Some drivers think it's safe to schedule isochronous transfers more than
++ * 256 ms into the future (partly as a result of an old bug in the scheduling
++ * code). In an attempt to avoid trouble, we will use a minimum scheduling
++ * length of 512 frames instead of 256.
++ */
++#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */
+
+ #define EHCI_IAA_MSECS 10 /* arbitrary */
+ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1395,28 +1395,31 @@ iso_stream_schedule (
+ struct ehci_iso_stream *stream
+ )
+ {
+- u32 now, next, start, period;
++ u32 now, next, start, period, span;
+ int status;
+ unsigned mod = ehci->periodic_size << 3;
+ struct ehci_iso_sched *sched = urb->hcpriv;
+
+- if (sched->span > (mod - SCHEDULE_SLOP)) {
++ period = urb->interval;
++ span = sched->span;
++ if (!stream->highspeed) {
++ period <<= 3;
++ span <<= 3;
++ }
++
++ if (span > mod - SCHEDULE_SLOP) {
+ ehci_dbg (ehci, "iso request %p too long\n", urb);
+ status = -EFBIG;
+ goto fail;
+ }
+
+- if ((stream->depth + sched->span) > mod) {
++ if (stream->depth + span > mod) {
+ ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+- urb, stream->depth, sched->span, mod);
++ urb, stream->depth, span, mod);
+ status = -EFBIG;
+ goto fail;
+ }
+
+- period = urb->interval;
+- if (!stream->highspeed)
+- period <<= 3;
+-
+ now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+
+ /* Typical case: reuse current schedule, stream is still active.
+@@ -1445,7 +1448,7 @@ iso_stream_schedule (
+ period);
+
+ /* Tried to schedule too far into the future? */
+- if (unlikely(((start - now) & (mod - 1)) + sched->span
++ if (unlikely(((start - now) & (mod - 1)) + span
+ >= mod - 2 * SCHEDULE_SLOP)) {
+ status = -EFBIG;
+ goto fail;
diff --git a/usb/usb-ehci-remove-dead-code-in-the-periodic-scheduler.patch b/usb/usb-ehci-remove-dead-code-in-the-periodic-scheduler.patch
new file mode 100644
index 00000000000000..daafb7c2e95162
--- /dev/null
+++ b/usb/usb-ehci-remove-dead-code-in-the-periodic-scheduler.patch
@@ -0,0 +1,108 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 15:52:31 2010
+Date: Wed, 14 Jul 2010 11:03:57 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: David Brownell <david-b@pacbell.net>,
+ USB list <linux-usb@vger.kernel.org>
+Subject: USB: EHCI: remove dead code in the periodic scheduler
+Message-ID: <Pine.LNX.4.44L0.1007141059480.1634-100000@iolanthe.rowland.org>
+
+This patch (as1409) removes some dead code from the ehci-hcd
+scheduler. Thanks to the previous patch in this series, stream->depth
+is no longer used. And stream->start and stream->rescheduled
+apparently have not been used for quite a while, except in some
+statistics-reporting code that never gets invoked.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: David Brownell <david-b@pacbell.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-sched.c | 15 ---------------
+ drivers/usb/host/ehci.h | 3 ---
+ 2 files changed, 18 deletions(-)
+
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1074,15 +1074,6 @@ iso_stream_put(struct ehci_hcd *ehci, st
+ if (stream->ep)
+ stream->ep->hcpriv = NULL;
+
+- if (stream->rescheduled) {
+- ehci_info (ehci, "ep%d%s-iso rescheduled "
+- "%lu times in %lu seconds\n",
+- stream->bEndpointAddress, is_in ? "in" : "out",
+- stream->rescheduled,
+- ((jiffies - stream->start)/HZ)
+- );
+- }
+-
+ kfree(stream);
+ }
+ }
+@@ -1617,7 +1608,6 @@ itd_link_urb (
+ (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+ urb->interval,
+ next_uframe >> 3, next_uframe & 0x7);
+- stream->start = jiffies;
+ }
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+
+@@ -1643,7 +1633,6 @@ itd_link_urb (
+ itd_patch(ehci, itd, iso_sched, packet, uframe);
+
+ next_uframe += stream->interval;
+- stream->depth += stream->interval;
+ next_uframe &= mod - 1;
+ packet++;
+
+@@ -1699,7 +1688,6 @@ itd_complete (
+
+ t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
+ itd->hw_transaction [uframe] = 0;
+- stream->depth -= stream->interval;
+
+ /* report transfer status */
+ if (unlikely (t & ISO_ERRS)) {
+@@ -2029,7 +2017,6 @@ sitd_link_urb (
+ (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+ (next_uframe >> 3) & (ehci->periodic_size - 1),
+ stream->interval, hc32_to_cpu(ehci, stream->splits));
+- stream->start = jiffies;
+ }
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+
+@@ -2054,7 +2041,6 @@ sitd_link_urb (
+ sitd);
+
+ next_uframe += stream->interval << 3;
+- stream->depth += stream->interval << 3;
+ }
+ stream->next_uframe = next_uframe & (mod - 1);
+
+@@ -2114,7 +2100,6 @@ sitd_complete (
+ desc->actual_length = desc->length - SITD_LENGTH(t);
+ urb->actual_length += desc->actual_length;
+ }
+- stream->depth -= stream->interval << 3;
+
+ /* handle completion now? */
+ if ((urb_index + 1) != urb->number_of_packets)
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -404,15 +404,12 @@ struct ehci_iso_stream {
+ u32 refcount;
+ u8 bEndpointAddress;
+ u8 highspeed;
+- u16 depth; /* depth in uframes */
+ struct list_head td_list; /* queued itds/sitds */
+ struct list_head free_list; /* list of unused itds/sitds */
+ struct usb_device *udev;
+ struct usb_host_endpoint *ep;
+
+ /* output of (re)scheduling */
+- unsigned long start; /* jiffies */
+- unsigned long rescheduled;
+ int next_uframe;
+ __hc32 splits;
+
diff --git a/usb/usb-ehci-remove-pci-assumption.patch b/usb/usb-ehci-remove-pci-assumption.patch
new file mode 100644
index 00000000000000..1c955f1bb89f19
--- /dev/null
+++ b/usb/usb-ehci-remove-pci-assumption.patch
@@ -0,0 +1,78 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 15:50:30 2010
+Date: Wed, 14 Jul 2010 11:03:23 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: Sarah Sharp <sarah.a.sharp@linux.intel.com>,
+ David Brownell <david-b@pacbell.net>,
+ USB list <linux-usb@vger.kernel.org>
+Subject: USB: EHCI: remove PCI assumption
+Message-ID: <Pine.LNX.4.44L0.1007141053530.1634-100000@iolanthe.rowland.org>
+
+This patch (as1405) fixes a small bug in ehci-hcd's isochronous
+scheduler. Not all EHCI controllers are PCI, and the code shouldn't
+assume that they are. Instead, introduce a special flag for
+controllers which need to delay iso scheduling for full-speed devices
+beyond the scheduling threshold.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+CC: David Brownell <david-b@pacbell.net>
+CC: stable <stable@kernel.org>
+Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+---
+ drivers/usb/host/ehci-pci.c | 1 +
+ drivers/usb/host/ehci-sched.c | 10 ++++------
+ drivers/usb/host/ehci.h | 1 +
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -114,6 +114,7 @@ static int ehci_pci_setup(struct usb_hcd
+ break;
+ case PCI_VENDOR_ID_INTEL:
+ ehci->need_io_watchdog = 0;
++ ehci->fs_i_thresh = 1;
+ if (pdev->device == 0x27cc) {
+ ehci->broken_periodic = 1;
+ ehci_info(ehci, "using broken periodic workaround\n");
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1399,7 +1399,6 @@ iso_stream_schedule (
+ int status;
+ unsigned mod = ehci->periodic_size << 3;
+ struct ehci_iso_sched *sched = urb->hcpriv;
+- struct pci_dev *pdev;
+
+ if (sched->span > (mod - SCHEDULE_SLOP)) {
+ ehci_dbg (ehci, "iso request %p too long\n", urb);
+@@ -1426,15 +1425,14 @@ iso_stream_schedule (
+ * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ */
+ if (likely (!list_empty (&stream->td_list))) {
+- pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
+ start = stream->next_uframe;
+
+ /* For high speed devices, allow scheduling within the
+- * isochronous scheduling threshold. For full speed devices,
+- * don't. (Work around for Intel ICH9 bug.)
++ * isochronous scheduling threshold. For full speed devices
++ * and Intel PCI-based controllers, don't (work around for
++ * Intel ICH9 bug).
+ */
+- if (!stream->highspeed &&
+- pdev->vendor == PCI_VENDOR_ID_INTEL)
++ if (!stream->highspeed && ehci->fs_i_thresh)
+ next = now + ehci->i_thresh;
+ else
+ next = now;
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -130,6 +130,7 @@ struct ehci_hcd { /* one per controlle
+ unsigned has_amcc_usb23:1;
+ unsigned need_io_watchdog:1;
+ unsigned broken_periodic:1;
++ unsigned fs_i_thresh:1; /* Intel iso scheduling */
+
+ /* required for usb32 quirk */
+ #define OHCI_CTRL_HCFS (3 << 6)
diff --git a/usb/usb-ehci-reorganize-isochronous-scheduler-routine.patch b/usb/usb-ehci-reorganize-isochronous-scheduler-routine.patch
new file mode 100644
index 00000000000000..3df776d50eea63
--- /dev/null
+++ b/usb/usb-ehci-reorganize-isochronous-scheduler-routine.patch
@@ -0,0 +1,188 @@
+From stern+4c290172@rowland.harvard.edu Thu Jul 22 15:52:14 2010
+Date: Wed, 14 Jul 2010 11:03:53 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: David Brownell <david-b@pacbell.net>, USB list <linux-usb@vger.kernel.org>
+Subject: USB: EHCI: reorganize isochronous scheduler routine
+Message-ID: <Pine.LNX.4.44L0.1007141058150.1634-100000@iolanthe.rowland.org>
+
+This patch (as1408) rearranges the scheduling code in ehci-hcd, partly
+to improve its structure, but mainly to change the way it works.
+Whether or not a transfer exceeds the hardware schedule length will
+now be determined by looking at the last frame the transfer would use,
+instead of the first available frame following the end of the transfer.
+
+The benefit of this change is that it allows the driver to accept
+valid URBs which would otherwise be rejected. For example, suppose
+the schedule length is 1024 frames, the endpoint period is 256 frames,
+and a four-packet URB is submitted. The four transfers would occupy
+slots that are 0, 256, 512, and 768 frames past the current frame
+(plus an extra slop factor). These don't exceed the 1024-frame limit,
+so the URB should be accepted. But the current code notices that the
+next available slot would be 1024 frames (plus slop) in the future,
+which is beyond the limit, and so the URB is rejected unnecessarily.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: David Brownell <david-b@pacbell.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/host/ehci-sched.c | 110 +++++++++++++++++++++---------------------
+ 1 file changed, 57 insertions(+), 53 deletions(-)
+
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1413,13 +1413,6 @@ iso_stream_schedule (
+ goto fail;
+ }
+
+- if (stream->depth + span > mod) {
+- ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+- urb, stream->depth, span, mod);
+- status = -EFBIG;
+- goto fail;
+- }
+-
+ now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+
+ /* Typical case: reuse current schedule, stream is still active.
+@@ -1428,7 +1421,7 @@ iso_stream_schedule (
+ * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ */
+ if (likely (!list_empty (&stream->td_list))) {
+- start = stream->next_uframe;
++ u32 excess;
+
+ /* For high speed devices, allow scheduling within the
+ * isochronous scheduling threshold. For full speed devices
+@@ -1440,21 +1433,23 @@ iso_stream_schedule (
+ else
+ next = now;
+
+- /* Fell behind (by up to twice the slop amount)? */
+- if (((start - next) & (mod - 1)) >=
+- mod - 2 * SCHEDULE_SLOP)
+- start += period * DIV_ROUND_UP(
+- (next - start) & (mod - 1),
+- period);
+-
+- /* Tried to schedule too far into the future? */
+- if (unlikely(((start - now) & (mod - 1)) + span
+- >= mod - 2 * SCHEDULE_SLOP)) {
++ /* Fell behind (by up to twice the slop amount)?
++ * We decide based on the time of the last currently-scheduled
++ * slot, not the time of the next available slot.
++ */
++ excess = (stream->next_uframe - period - next) & (mod - 1);
++ if (excess >= mod - 2 * SCHEDULE_SLOP)
++ start = next + excess - mod + period *
++ DIV_ROUND_UP(mod - excess, period);
++ else
++ start = next + excess + period;
++ if (start - now >= mod) {
++ ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
++ urb, start - now - period, period,
++ mod);
+ status = -EFBIG;
+ goto fail;
+ }
+- stream->next_uframe = start;
+- goto ready;
+ }
+
+ /* need to schedule; when's the next (u)frame we could start?
+@@ -1463,51 +1458,60 @@ iso_stream_schedule (
+ * can also help high bandwidth if the dma and irq loads don't
+ * jump until after the queue is primed.
+ */
+- start = SCHEDULE_SLOP + (now & ~0x07);
+- start &= mod - 1;
+- stream->next_uframe = start;
+-
+- /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
+-
+- /* find a uframe slot with enough bandwidth */
+- for (; start < (stream->next_uframe + period); start++) {
+- int enough_space;
+-
+- /* check schedule: enough space? */
+- if (stream->highspeed)
+- enough_space = itd_slot_ok (ehci, mod, start,
+- stream->usecs, period);
+- else {
+- if ((start % 8) >= 6)
+- continue;
+- enough_space = sitd_slot_ok (ehci, mod, stream,
+- start, sched, period);
++ else {
++ start = SCHEDULE_SLOP + (now & ~0x07);
++
++ /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
++
++ /* find a uframe slot with enough bandwidth */
++ next = start + period;
++ for (; start < next; start++) {
++
++ /* check schedule: enough space? */
++ if (stream->highspeed) {
++ if (itd_slot_ok(ehci, mod, start,
++ stream->usecs, period))
++ break;
++ } else {
++ if ((start % 8) >= 6)
++ continue;
++ if (sitd_slot_ok(ehci, mod, stream,
++ start, sched, period))
++ break;
++ }
+ }
+
+- /* schedule it here if there's enough bandwidth */
+- if (enough_space) {
+- stream->next_uframe = start & (mod - 1);
+- goto ready;
++ /* no room in the schedule */
++ if (start == next) {
++ ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
++ urb, now, now + mod);
++ status = -ENOSPC;
++ goto fail;
+ }
+ }
+
+- /* no room in the schedule */
+- ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n",
+- list_empty (&stream->td_list) ? "" : "re",
+- urb, now, now + mod);
+- status = -ENOSPC;
++ /* Tried to schedule too far into the future? */
++ if (unlikely(start - now + span - period
++ >= mod - 2 * SCHEDULE_SLOP)) {
++ ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
++ urb, start - now, span - period,
++ mod - 2 * SCHEDULE_SLOP);
++ status = -EFBIG;
++ goto fail;
++ }
+
+-fail:
+- iso_sched_free (stream, sched);
+- urb->hcpriv = NULL;
+- return status;
++ stream->next_uframe = start & (mod - 1);
+
+-ready:
+ /* report high speed start in uframes; full speed, in frames */
+ urb->start_frame = stream->next_uframe;
+ if (!stream->highspeed)
+ urb->start_frame >>= 3;
+ return 0;
++
++ fail:
++ iso_sched_free(stream, sched);
++ urb->hcpriv = NULL;
++ return status;
+ }
+
+ /*-------------------------------------------------------------------------*/
diff --git a/usb/usb-ehci-simplify-remainder-computations.patch b/usb/usb-ehci-simplify-remainder-computations.patch
new file mode 100644
index 00000000000000..d49e13986c755d
--- /dev/null
+++ b/usb/usb-ehci-simplify-remainder-computations.patch
@@ -0,0 +1,148 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 15:51:42 2010
+Date: Wed, 14 Jul 2010 11:03:36 -0400 (EDT)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: David Brownell <david-b@pacbell.net>,
+ USB list <linux-usb@vger.kernel.org>
+Subject: USB: EHCI: simplify remainder computations
+Message-ID: <Pine.LNX.4.44L0.1007141055270.1634-100000@iolanthe.rowland.org>
+
+This patch (as1406) adds a micro-optimization to ehci-hcd's scheduling
+code. Instead of computing remainders with respect to the schedule
+length, use bitwise-and (which is quicker). We know that the schedule
+length will always be a power of two, but the compiler doesn't have
+this information.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+CC: David Brownell <david-b@pacbell.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-sched.c | 29 +++++++++++++++--------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1417,7 +1417,7 @@ iso_stream_schedule (
+ if (!stream->highspeed)
+ period <<= 3;
+
+- now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
++ now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+
+ /* Typical case: reuse current schedule, stream is still active.
+ * Hopefully there are no gaps from the host falling behind
+@@ -1461,7 +1461,7 @@ iso_stream_schedule (
+ * jump until after the queue is primed.
+ */
+ start = SCHEDULE_SLOP + (now & ~0x07);
+- start %= mod;
++ start &= mod - 1;
+ stream->next_uframe = start;
+
+ /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
+@@ -1483,7 +1483,7 @@ iso_stream_schedule (
+
+ /* schedule it here if there's enough bandwidth */
+ if (enough_space) {
+- stream->next_uframe = start % mod;
++ stream->next_uframe = start & (mod - 1);
+ goto ready;
+ }
+ }
+@@ -1599,7 +1599,7 @@ itd_link_urb (
+ struct ehci_iso_sched *iso_sched = urb->hcpriv;
+ struct ehci_itd *itd;
+
+- next_uframe = stream->next_uframe % mod;
++ next_uframe = stream->next_uframe & (mod - 1);
+
+ if (unlikely (list_empty(&stream->td_list))) {
+ ehci_to_hcd(ehci)->self.bandwidth_allocated
+@@ -1637,13 +1637,13 @@ itd_link_urb (
+
+ next_uframe += stream->interval;
+ stream->depth += stream->interval;
+- next_uframe %= mod;
++ next_uframe &= mod - 1;
+ packet++;
+
+ /* link completed itds into the schedule */
+ if (((next_uframe >> 3) != frame)
+ || packet == urb->number_of_packets) {
+- itd_link (ehci, frame % ehci->periodic_size, itd);
++ itd_link(ehci, frame & (ehci->periodic_size - 1), itd);
+ itd = NULL;
+ }
+ }
+@@ -2020,7 +2020,7 @@ sitd_link_urb (
+ "sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
+ urb->dev->devpath, stream->bEndpointAddress & 0x0f,
+ (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+- (next_uframe >> 3) % ehci->periodic_size,
++ (next_uframe >> 3) & (ehci->periodic_size - 1),
+ stream->interval, hc32_to_cpu(ehci, stream->splits));
+ stream->start = jiffies;
+ }
+@@ -2043,13 +2043,13 @@ sitd_link_urb (
+ sitd->urb = urb;
+
+ sitd_patch(ehci, stream, sitd, sched, packet);
+- sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
++ sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1),
+ sitd);
+
+ next_uframe += stream->interval << 3;
+ stream->depth += stream->interval << 3;
+ }
+- stream->next_uframe = next_uframe % mod;
++ stream->next_uframe = next_uframe & (mod - 1);
+
+ /* don't need that schedule data any more */
+ iso_sched_free (stream, sched);
+@@ -2258,7 +2258,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ now_uframe = ehci->next_uframe;
+ if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+ clock = ehci_readl(ehci, &ehci->regs->frame_index);
+- clock_frame = (clock >> 3) % ehci->periodic_size;
++ clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+ } else {
+ clock = now_uframe + mod - 1;
+ clock_frame = -1;
+@@ -2267,7 +2267,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ free_cached_lists(ehci);
+ ehci->clock_frame = clock_frame;
+ }
+- clock %= mod;
++ clock &= mod - 1;
+ clock_frame = clock >> 3;
+
+ for (;;) {
+@@ -2356,7 +2356,7 @@ restart:
+ * frame is current.
+ */
+ if (((frame == clock_frame) ||
+- (((frame + 1) % ehci->periodic_size)
++ (((frame + 1) & (ehci->periodic_size - 1))
+ == clock_frame))
+ && live
+ && (q.sitd->hw_results &
+@@ -2423,7 +2423,8 @@ restart:
+ || ehci->periodic_sched == 0)
+ break;
+ ehci->next_uframe = now_uframe;
+- now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
++ now = ehci_readl(ehci, &ehci->regs->frame_index) &
++ (mod - 1);
+ if (now_uframe == now)
+ break;
+
+@@ -2436,7 +2437,7 @@ restart:
+ }
+ } else {
+ now_uframe++;
+- now_uframe %= mod;
++ now_uframe &= mod - 1;
+ }
+ }
+ }
diff --git a/usb/usb-gadget-functionfs-stale-makefile-entry-removed.patch b/usb/usb-gadget-functionfs-stale-makefile-entry-removed.patch
new file mode 100644
index 00000000000000..e4db7eac165a22
--- /dev/null
+++ b/usb/usb-gadget-functionfs-stale-makefile-entry-removed.patch
@@ -0,0 +1,31 @@
+From m.nazarewicz@samsung.com Thu Jul 22 15:54:07 2010
+Date: Mon, 19 Jul 2010 11:47:04 +0200
+From: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Subject: USB: gadget: functionfs: stale Makefile entry removed
+To: linux-usb@vger.kernel.org
+Cc: Michal Nazarewicz <m.nazarewicz@samsung.com>, Greg KH <greg@kroah.com>,
+ "Robert P. J. Day" <rpjday@crashcourse.ca>, linux-kernel@vger.kernel.org
+Message-id: <56bb448ef3f882f8fdc6a80613a841a729755cc9.1279532379.git.m.nazarewicz@samsung.com>
+
+Removed entry referencing g_eth_ffs.c file from Makefile.
+The file never existed and the line was a leftover from a
+developing process.
+
+Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
+Reported-by: Robert P. J. Day <rpjday@crashcourse.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/Makefile | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/usb/gadget/Makefile
++++ b/drivers/usb/gadget/Makefile
+@@ -53,7 +53,6 @@ obj-$(CONFIG_USB_AUDIO) += g_audio.o
+ obj-$(CONFIG_USB_ETH) += g_ether.o
+ obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
+ obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
+-obj-$(CONFIG_USB_ETH_FUNCTIONFS) += g_eth_ffs.o
+ obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
+ obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
+ obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
diff --git a/usb/usb-gadget-storage-optional-scsi-write-fua-bit.patch b/usb/usb-gadget-storage-optional-scsi-write-fua-bit.patch
new file mode 100644
index 00000000000000..3755e1ba7294dd
--- /dev/null
+++ b/usb/usb-gadget-storage-optional-scsi-write-fua-bit.patch
@@ -0,0 +1,217 @@
+From andy.shevchenko@gmail.com Thu Jul 22 16:47:18 2010
+From: Andy Shevchenko <andy.shevchenko@gmail.com>
+To: linux-kernel@vger.kernel.org
+Cc: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>,
+ Denis Karpov <ext-denis.2.karpov@nokia.com>,
+ Adrian Hunter <adrian.hunter@nokia.com>,
+ Alan Stern <stern@rowland.harvard.edu>,
+ David Brownell <dbrownell@users.sourceforge.net>,
+ Greg Kroah-Hartman <gregkh@suse.de>, linux-usb@vger.kernel.org
+Subject: USB: gadget: storage: optional SCSI WRITE FUA bit
+Date: Thu, 22 Jul 2010 17:53:56 +0300
+Message-Id: <1279810436-15678-1-git-send-email-ext-andriy.shevchenko@nokia.com>
+
+MS Windows mounts removable storage in "Removal optimized mode" by
+default. All the writes to the media are synchronous which is achieved
+by setting FUA (Force Unit Access) bit in SCSI WRITE(10,12) commands.
+This prevents I/O requests aggregation in block layer dramatically
+decreasing performance.
+
+This patch brings an option to accept or ignore mentioned bit
+ a) via specifying module parameter "nofua", or
+ b) through sysfs entry
+ /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua
+ (_UDC_ is the name of the USB Device Controller driver)
+
+Patch is based on the work that was done by Denis Karpov for Maemo 5
+platform.
+
+Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: Denis Karpov <ext-denis.2.karpov@nokia.com>
+Cc: Adrian Hunter <adrian.hunter@nokia.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget | 12 +++
+ drivers/usb/gadget/file_storage.c | 31 +++++++---
+ drivers/usb/gadget/storage_common.c | 28 +++++++++
+ 3 files changed, 64 insertions(+), 7 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
++++ b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget
+@@ -7,3 +7,15 @@ Description:
+ 0 -> resumed
+
+ (_UDC_ is the name of the USB Device Controller driver)
++
++What: /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua
++Date: July 2010
++Contact: Andy Shevchenko <andy.shevchenko@gmail.com>
++Description:
++ Show or set the reaction on the FUA (Force Unit Access) bit in
++ the SCSI WRITE(10,12) commands when a gadget in USB Mass
++ Storage mode.
++
++ Possible values are:
++ 1 -> ignore the FUA flag
++ 0 -> obey the FUA flag
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -93,6 +93,8 @@
+ * removable Default false, boolean for removable media
+ * luns=N Default N = number of filenames, number of
+ * LUNs to support
++ * nofua=b[,b...] Default false, booleans for ignore FUA flag
++ * in SCSI WRITE(10,12) commands
+ * stall Default determined according to the type of
+ * USB device controller (usually true),
+ * boolean to permit the driver to halt
+@@ -112,12 +114,12 @@
+ * PAGE_CACHE_SIZE)
+ *
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+- * "removable", "luns", "stall", and "cdrom" options are available; default
+- * values are used for everything else.
++ * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
++ * default values are used for everything else.
+ *
+ * The pathnames of the backing files and the ro settings are available in
+- * the attribute files "file" and "ro" in the lun<n> subdirectory of the
+- * gadget's sysfs directory. If the "removable" option is set, writing to
++ * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
++ * the gadget's sysfs directory. If the "removable" option is set, writing to
+ * these files will simulate ejecting/loading the medium (writing an empty
+ * line means eject) and adjusting a write-enable tab. Changes to the ro
+ * setting are not allowed when the medium is loaded or if CD-ROM emulation
+@@ -304,8 +306,10 @@ MODULE_LICENSE("Dual BSD/GPL");
+ static struct {
+ char *file[FSG_MAX_LUNS];
+ int ro[FSG_MAX_LUNS];
++ int nofua[FSG_MAX_LUNS];
+ unsigned int num_filenames;
+ unsigned int num_ros;
++ unsigned int num_nofuas;
+ unsigned int nluns;
+
+ int removable;
+@@ -345,6 +349,10 @@ MODULE_PARM_DESC(file, "names of backing
+ module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
+ MODULE_PARM_DESC(ro, "true to force read-only");
+
++module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
++ S_IRUGO);
++MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
++
+ module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
+ MODULE_PARM_DESC(luns, "number of LUNs");
+
+@@ -1279,7 +1287,8 @@ static int do_write(struct fsg_dev *fsg)
+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
+ return -EINVAL;
+ }
+- if (fsg->cmnd[1] & 0x08) { // FUA
++ /* FUA */
++ if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
+ spin_lock(&curlun->filp->f_lock);
+ curlun->filp->f_flags |= O_DSYNC;
+ spin_unlock(&curlun->filp->f_lock);
+@@ -3133,6 +3142,7 @@ static int fsg_main_thread(void *fsg_)
+
+ /* The write permissions and store_xxx pointers are set in fsg_bind() */
+ static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
++static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
+ static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
+
+
+@@ -3362,6 +3372,10 @@ static int __ref fsg_bind(struct usb_gad
+ }
+ }
+
++ /* Only for removable media? */
++ dev_attr_nofua.attr.mode = 0644;
++ dev_attr_nofua.store = fsg_store_nofua;
++
+ /* Find out how many LUNs there should be */
+ i = mod_data.nluns;
+ if (i == 0)
+@@ -3387,6 +3401,7 @@ static int __ref fsg_bind(struct usb_gad
+ curlun->ro = mod_data.cdrom || mod_data.ro[i];
+ curlun->initially_ro = curlun->ro;
+ curlun->removable = mod_data.removable;
++ curlun->nofua = mod_data.nofua[i];
+ curlun->dev.release = lun_release;
+ curlun->dev.parent = &gadget->dev;
+ curlun->dev.driver = &fsg_driver.driver;
+@@ -3401,6 +3416,8 @@ static int __ref fsg_bind(struct usb_gad
+ if ((rc = device_create_file(&curlun->dev,
+ &dev_attr_ro)) != 0 ||
+ (rc = device_create_file(&curlun->dev,
++ &dev_attr_nofua)) != 0 ||
++ (rc = device_create_file(&curlun->dev,
+ &dev_attr_file)) != 0) {
+ device_unregister(&curlun->dev);
+ goto out;
+@@ -3525,8 +3542,8 @@ static int __ref fsg_bind(struct usb_gad
+ if (IS_ERR(p))
+ p = NULL;
+ }
+- LINFO(curlun, "ro=%d, file: %s\n",
+- curlun->ro, (p ? p : "(error)"));
++ LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
++ curlun->ro, curlun->nofua, (p ? p : "(error)"));
+ }
+ }
+ kfree(pathbuf);
+--- a/drivers/usb/gadget/storage_common.c
++++ b/drivers/usb/gadget/storage_common.c
+@@ -284,6 +284,7 @@ struct fsg_lun {
+ unsigned int prevent_medium_removal:1;
+ unsigned int registered:1;
+ unsigned int info_valid:1;
++ unsigned int nofua:1;
+
+ u32 sense_data;
+ u32 sense_data_info;
+@@ -714,6 +715,14 @@ static ssize_t fsg_show_ro(struct device
+ : curlun->initially_ro);
+ }
+
++static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct fsg_lun *curlun = fsg_lun_from_dev(dev);
++
++ return sprintf(buf, "%u\n", curlun->nofua);
++}
++
+ static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+@@ -770,6 +779,25 @@ static ssize_t fsg_store_ro(struct devic
+ return rc;
+ }
+
++static ssize_t fsg_store_nofua(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fsg_lun *curlun = fsg_lun_from_dev(dev);
++ unsigned long nofua;
++
++ if (strict_strtoul(buf, 2, &nofua))
++ return -EINVAL;
++
++ /* Sync data when switching from async mode to sync */
++ if (!nofua && curlun->nofua)
++ fsg_lun_fsync_sub(curlun);
++
++ curlun->nofua = nofua;
++
++ return count;
++}
++
+ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
diff --git a/usb/usb-gadget-storage-strict-coversion-of-ro-parameter.patch b/usb/usb-gadget-storage-strict-coversion-of-ro-parameter.patch
new file mode 100644
index 00000000000000..4bc783cc215c4b
--- /dev/null
+++ b/usb/usb-gadget-storage-strict-coversion-of-ro-parameter.patch
@@ -0,0 +1,54 @@
+From andy.shevchenko@gmail.com Thu Jul 22 16:46:41 2010
+From: Andy Shevchenko <andy.shevchenko@gmail.com>
+To: linux-kernel@vger.kernel.org
+Cc: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>,
+ Alan Stern <stern@rowland.harvard.edu>,
+ David Brownell <dbrownell@users.sourceforge.net>,
+ Greg Kroah-Hartman <gregkh@suse.de>, linux-usb@vger.kernel.org
+Subject: usb: gadget: storage: strict coversion of 'ro' parameter
+Date: Thu, 22 Jul 2010 11:58:47 +0300
+Message-Id: <1279789128-11399-1-git-send-email-ext-andriy.shevchenko@nokia.com>
+
+Bring a strict way to get the 'ro' parameter from the user.
+
+The patch followed by this one adds another boolean parameter. To be consistent
+Michał Nazarewicz proposed to use simple_strtol() in both cases (correspondend
+discussion in LKML [1]). Due to simple_strtol() doesn't return error in a good
+way and we have a boolean parameter the strict_strtoul() is used.
+
+[1] http://lkml.org/lkml/2010/7/14/169
+
+Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/storage_common.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/gadget/storage_common.c
++++ b/drivers/usb/gadget/storage_common.c
+@@ -748,9 +748,9 @@ static ssize_t fsg_store_ro(struct devic
+ ssize_t rc = count;
+ struct fsg_lun *curlun = fsg_lun_from_dev(dev);
+ struct rw_semaphore *filesem = dev_get_drvdata(dev);
+- int i;
++ unsigned long ro;
+
+- if (sscanf(buf, "%d", &i) != 1)
++ if (strict_strtoul(buf, 2, &ro))
+ return -EINVAL;
+
+ /*
+@@ -762,8 +762,8 @@ static ssize_t fsg_store_ro(struct devic
+ LDBG(curlun, "read-only status change prevented\n");
+ rc = -EBUSY;
+ } else {
+- curlun->ro = !!i;
+- curlun->initially_ro = !!i;
++ curlun->ro = ro;
++ curlun->initially_ro = ro;
+ LDBG(curlun, "read-only status set to %d\n", curlun->ro);
+ }
+ up_read(filesem);
diff --git a/usb/usb-host-sl811-hcd-check-kzalloc-result.patch b/usb/usb-host-sl811-hcd-check-kzalloc-result.patch
new file mode 100644
index 00000000000000..cdcfa5c1c10558
--- /dev/null
+++ b/usb/usb-host-sl811-hcd-check-kzalloc-result.patch
@@ -0,0 +1,37 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 16:48:01 2010
+From: Kulikov Vasiliy <segooon@gmail.com>
+To: kernel-janitors@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@suse.de>,
+ Mike Frysinger <vapier@gentoo.org>,
+ Alan Stern <stern@rowland.harvard.edu>,
+ Michael Hennerich <michael.hennerich@analog.com>,
+ Bryan Wu <cooloney@kernel.org>, linux-usb@vger.kernel.org,
+ linux-kernel@vger.kernel.org
+Subject: usb: host: sl811-hcd: check kzalloc() result
+Date: Fri, 16 Jul 2010 20:15:06 +0400
+Message-Id: <1279296906-25107-1-git-send-email-segooon@gmail.com>
+
+If kzalloc() fails exit with -ENOMEM.
+
+Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/sl811-hcd.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -813,8 +813,11 @@ static int sl811h_urb_enqueue(
+ #endif
+
+ /* avoid all allocations within spinlocks */
+- if (!hep->hcpriv)
++ if (!hep->hcpriv) {
+ ep = kzalloc(sizeof *ep, mem_flags);
++ if (ep == NULL)
++ return -ENOMEM;
++ }
+
+ spin_lock_irqsave(&sl811->lock, flags);
+
diff --git a/usb/usb-option-huawei-ets-1220-support-added.patch b/usb/usb-option-huawei-ets-1220-support-added.patch
new file mode 100644
index 00000000000000..645fec434fcb5a
--- /dev/null
+++ b/usb/usb-option-huawei-ets-1220-support-added.patch
@@ -0,0 +1,38 @@
+From p.i.kazlou@gmail.com Thu Jul 22 15:59:39 2010
+Date: Thu, 22 Jul 2010 03:22:20 +0300
+From: Pavel Kazlou <p.i.kazlou@gmail.com>
+To: Greg Kroah-Hartman <greg@kroah.com>
+Cc: linux-usb@vger.kernel.org
+Subject: USB: option: Huawei ETS 1220 support added
+Message-ID: <20100722032220.647ef563@gmail.com>
+
+From: Pavel Kazlou <p.i.kazlou@gmail.com>
+
+The patch adds Huawei ETS 1220 product id into the list of supported
+devices in 'option' usb serial driver.
+
+Signed-off-by: Pavel Kazlou <p.i.kazlou@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -146,6 +146,7 @@ static void option_instat_callback(struc
+ #define HUAWEI_PRODUCT_E143E 0x143E
+ #define HUAWEI_PRODUCT_E143F 0x143F
+ #define HUAWEI_PRODUCT_E14AC 0x14AC
++#define HUAWEI_PRODUCT_ETS1220 0x1803
+
+ #define QUANTA_VENDOR_ID 0x0408
+ #define QUANTA_PRODUCT_Q101 0xEA02
+@@ -479,6 +480,7 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
diff --git a/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch b/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch
new file mode 100644
index 00000000000000..a8fd3e68c83ae2
--- /dev/null
+++ b/usb/usb-powerpc-fsl_soc.c-remove-fsl-usb-platform-code.patch
@@ -0,0 +1,198 @@
+From agust@denx.de Thu Jul 22 16:53:55 2010
+From: Anatolij Gustschin <agust@denx.de>
+To: linux-usb@vger.kernel.org
+Cc: linuxppc-dev@ozlabs.org, Greg Kroah-Hartman <gregkh@suse.de>,
+ David Brownell <dbrownell@users.sourceforge.net>,
+ Grant Likely <grant.likely@secretlab.ca>,
+ Detlev Zundel <dzu@denx.de>, Wolfgang Denk <wd@denx.de>,
+ Anatolij Gustschin <agust@denx.de>,
+ Kumar Gala <galak@kernel.crashing.org>
+Subject: USB: powerpc/fsl_soc.c: remove FSL USB platform code
+Date: Thu, 22 Jul 2010 18:25:20 +0200
+Message-Id: <1279815922-27198-2-git-send-email-agust@denx.de>
+
+This removed code will be replaced by simple of_platform
+driver for creation of FSL USB platform devices which is
+added by next patch of the series.
+
+Signed-off-by: Anatolij Gustschin <agust@denx.de>
+Cc: Kumar Gala <galak@kernel.crashing.org>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/powerpc/sysdev/fsl_soc.c | 163 ------------------------------------------
+ 1 file changed, 163 deletions(-)
+
+--- a/arch/powerpc/sysdev/fsl_soc.c
++++ b/arch/powerpc/sysdev/fsl_soc.c
+@@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void
+ arch_initcall(of_add_fixed_phys);
+ #endif /* CONFIG_FIXED_PHY */
+
+-static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
+-{
+- if (!phy_type)
+- return FSL_USB2_PHY_NONE;
+- if (!strcasecmp(phy_type, "ulpi"))
+- return FSL_USB2_PHY_ULPI;
+- if (!strcasecmp(phy_type, "utmi"))
+- return FSL_USB2_PHY_UTMI;
+- if (!strcasecmp(phy_type, "utmi_wide"))
+- return FSL_USB2_PHY_UTMI_WIDE;
+- if (!strcasecmp(phy_type, "serial"))
+- return FSL_USB2_PHY_SERIAL;
+-
+- return FSL_USB2_PHY_NONE;
+-}
+-
+-static int __init fsl_usb_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i = 0;
+- struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
+- *usb_dev_dr_client = NULL;
+- int ret;
+-
+- for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
+- struct resource r[2];
+- struct fsl_usb2_platform_data usb_data;
+- const unsigned char *prop = NULL;
+-
+- memset(&r, 0, sizeof(r));
+- memset(&usb_data, 0, sizeof(usb_data));
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto err;
+-
+- of_irq_to_resource(np, 0, &r[1]);
+-
+- usb_dev_mph =
+- platform_device_register_simple("fsl-ehci", i, r, 2);
+- if (IS_ERR(usb_dev_mph)) {
+- ret = PTR_ERR(usb_dev_mph);
+- goto err;
+- }
+-
+- usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
+- usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
+-
+- usb_data.operating_mode = FSL_USB2_MPH_HOST;
+-
+- prop = of_get_property(np, "port0", NULL);
+- if (prop)
+- usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
+-
+- prop = of_get_property(np, "port1", NULL);
+- if (prop)
+- usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
+-
+- prop = of_get_property(np, "phy_type", NULL);
+- usb_data.phy_mode = determine_usb_phy(prop);
+-
+- ret =
+- platform_device_add_data(usb_dev_mph, &usb_data,
+- sizeof(struct
+- fsl_usb2_platform_data));
+- if (ret)
+- goto unreg_mph;
+- i++;
+- }
+-
+- for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
+- struct resource r[2];
+- struct fsl_usb2_platform_data usb_data;
+- const unsigned char *prop = NULL;
+-
+- if (!of_device_is_available(np))
+- continue;
+-
+- memset(&r, 0, sizeof(r));
+- memset(&usb_data, 0, sizeof(usb_data));
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto unreg_mph;
+-
+- of_irq_to_resource(np, 0, &r[1]);
+-
+- prop = of_get_property(np, "dr_mode", NULL);
+-
+- if (!prop || !strcmp(prop, "host")) {
+- usb_data.operating_mode = FSL_USB2_DR_HOST;
+- usb_dev_dr_host = platform_device_register_simple(
+- "fsl-ehci", i, r, 2);
+- if (IS_ERR(usb_dev_dr_host)) {
+- ret = PTR_ERR(usb_dev_dr_host);
+- goto err;
+- }
+- } else if (prop && !strcmp(prop, "peripheral")) {
+- usb_data.operating_mode = FSL_USB2_DR_DEVICE;
+- usb_dev_dr_client = platform_device_register_simple(
+- "fsl-usb2-udc", i, r, 2);
+- if (IS_ERR(usb_dev_dr_client)) {
+- ret = PTR_ERR(usb_dev_dr_client);
+- goto err;
+- }
+- } else if (prop && !strcmp(prop, "otg")) {
+- usb_data.operating_mode = FSL_USB2_DR_OTG;
+- usb_dev_dr_host = platform_device_register_simple(
+- "fsl-ehci", i, r, 2);
+- if (IS_ERR(usb_dev_dr_host)) {
+- ret = PTR_ERR(usb_dev_dr_host);
+- goto err;
+- }
+- usb_dev_dr_client = platform_device_register_simple(
+- "fsl-usb2-udc", i, r, 2);
+- if (IS_ERR(usb_dev_dr_client)) {
+- ret = PTR_ERR(usb_dev_dr_client);
+- goto err;
+- }
+- } else {
+- ret = -EINVAL;
+- goto err;
+- }
+-
+- prop = of_get_property(np, "phy_type", NULL);
+- usb_data.phy_mode = determine_usb_phy(prop);
+-
+- if (usb_dev_dr_host) {
+- usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
+- usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
+- dev.coherent_dma_mask;
+- if ((ret = platform_device_add_data(usb_dev_dr_host,
+- &usb_data, sizeof(struct
+- fsl_usb2_platform_data))))
+- goto unreg_dr;
+- }
+- if (usb_dev_dr_client) {
+- usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
+- usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
+- dev.coherent_dma_mask;
+- if ((ret = platform_device_add_data(usb_dev_dr_client,
+- &usb_data, sizeof(struct
+- fsl_usb2_platform_data))))
+- goto unreg_dr;
+- }
+- i++;
+- }
+- return 0;
+-
+-unreg_dr:
+- if (usb_dev_dr_host)
+- platform_device_unregister(usb_dev_dr_host);
+- if (usb_dev_dr_client)
+- platform_device_unregister(usb_dev_dr_client);
+-unreg_mph:
+- if (usb_dev_mph)
+- platform_device_unregister(usb_dev_mph);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(fsl_usb_of_init);
+-
+ #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+ static __be32 __iomem *rstcr;
+
diff --git a/usb/usb-resizing-usbmon-binary-interface-buffer-causes-protection-faults.patch b/usb/usb-resizing-usbmon-binary-interface-buffer-causes-protection-faults.patch
new file mode 100644
index 00000000000000..cd5eb6fb2b117d
--- /dev/null
+++ b/usb/usb-resizing-usbmon-binary-interface-buffer-causes-protection-faults.patch
@@ -0,0 +1,35 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 15:57:03 2010
+Message-ID: <4C475AD4.8090000@strobe.cc>
+Date: Wed, 21 Jul 2010 16:38:44 -0400
+From: Steven Robertson <steven@strobe.cc>
+To: linux-usb@vger.kernel.org, greg@kroah.com
+Subject: USB: resizing usbmon binary interface buffer causes protection faults
+
+Enlarging the buffer size via the MON_IOCT_RING_SIZE ioctl causes
+general protection faults. It appears the culprit is an incorrect
+argument to mon_free_buff: instead of passing the size of the current
+buffer being freed, the size of the new buffer is passed.
+
+Use the correct size argument to mon_free_buff when changing the size of
+the buffer.
+
+Signed-off-by: Steven Robertson <steven@strobe.cc>
+Acked-by: Pete Zaitcev <zaitcev@redhat.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/mon/mon_bin.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -1004,7 +1004,7 @@ static long mon_bin_ioctl(struct file *f
+
+ mutex_lock(&rp->fetch_lock);
+ spin_lock_irqsave(&rp->b_lock, flags);
+- mon_free_buff(rp->b_vec, size/CHUNK_SIZE);
++ mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+ kfree(rp->b_vec);
+ rp->b_vec = vec;
+ rp->b_size = size;
diff --git a/usb/usb-s3c-hsotg-add-initial-detection-and-setup-for-dedicated-fifo-mode.patch b/usb/usb-s3c-hsotg-add-initial-detection-and-setup-for-dedicated-fifo-mode.patch
new file mode 100644
index 00000000000000..979cc20a480e2a
--- /dev/null
+++ b/usb/usb-s3c-hsotg-add-initial-detection-and-setup-for-dedicated-fifo-mode.patch
@@ -0,0 +1,166 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:25 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Add initial detection and setup for dedicated FIFO mode
+Date: Mon, 19 Jul 2010 09:40:44 +0100
+Message-Id: <1279528850-28245-6-git-send-email-ben-linux@fluff.org>
+
+Add support for the dedicated FIFO mode on newer SoCs such as the S5PV210
+partly to improve support and to fix the bug where any non-EP0 IN endpoint
+requires its own FIFO allocation.
+
+To fix this, we ensure that any non-zero IN endpoint is given a TXFIFO
+using the same allocation method as the periodic case (all our current
+hardware has enough FIFOs and FIFO memory for a 1:1 mapping) and ensure
+that the necessary transmission done interrupt is enabled.
+
+The default settings from reset for the core point all EPs at FIFO0,
+used for the control endpoint. However, the controller documentation
+states that all IN endpoints _must_ have a unique FIFO to avoid any
+contention during transmission.
+
+Note, this leaves us with a large IN FIFO for EP0 (which re-uses the
+old NPTXFIFO) for an endpoint which cannot shift more than a pair of
+packets at a time... this is a waste, but it looks like we cannot
+re-allocate space to the individual IN FIFOs as they are already
+maxed out (to be confirmed).
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h | 2 +
+ drivers/usb/gadget/s3c-hsotg.c | 40 +++++++++++++++++++-
+ 2 files changed, 40 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
++++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
+@@ -226,6 +226,7 @@
+
+ #define S3C_DIEPMSK S3C_HSOTG_REG(0x810)
+
++#define S3C_DIEPMSK_TxFIFOEmpty (1 << 7)
+ #define S3C_DIEPMSK_INEPNakEffMsk (1 << 6)
+ #define S3C_DIEPMSK_INTknEPMisMsk (1 << 5)
+ #define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4)
+@@ -371,6 +372,7 @@
+
+ #define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
+ #define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
++#define S3C_DTXFSTS(_a) S3C_HSOTG_REG(0x918 + ((_a) * 0x20))
+
+ #define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -12,6 +12,8 @@
+ * published by the Free Software Foundation.
+ */
+
++#define DEBUG
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+@@ -130,6 +132,7 @@ struct s3c_hsotg_ep {
+ * @regs: The memory area mapped for accessing registers.
+ * @regs_res: The resource that was allocated when claiming register space.
+ * @irq: The IRQ number we are using
++ * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @debug_root: root directrory for debugfs.
+ * @debug_file: main status file for debugfs.
+ * @debug_fifo: FIFO status file for debugfs.
+@@ -148,6 +151,8 @@ struct s3c_hsotg {
+ struct resource *regs_res;
+ int irq;
+
++ unsigned int dedicated_fifos:1;
++
+ struct dentry *debug_root;
+ struct dentry *debug_file;
+ struct dentry *debug_fifo;
+@@ -466,7 +471,7 @@ static int s3c_hsotg_write_fifo(struct s
+ if (to_write == 0)
+ return 0;
+
+- if (periodic) {
++ if (periodic && !hsotg->dedicated_fifos) {
+ u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
+ int size_left;
+ int size_done;
+@@ -504,6 +509,11 @@ static int s3c_hsotg_write_fifo(struct s
+ s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+ return -ENOSPC;
+ }
++ } else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
++ can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index));
++
++ can_write &= 0xffff;
++ can_write *= 4;
+ } else {
+ if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
+ dev_dbg(hsotg->dev,
+@@ -1829,6 +1839,15 @@ static void s3c_hsotg_epint(struct s3c_h
+ __func__, idx);
+ clear |= S3C_DIEPMSK_INTknEPMisMsk;
+ }
++
++ /* FIFO has space or is empty (see GAHBCFG) */
++ if (hsotg->dedicated_fifos &&
++ ints & S3C_DIEPMSK_TxFIFOEmpty) {
++ dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
++ __func__, idx);
++ s3c_hsotg_trytx(hsotg, hs_ep);
++ clear |= S3C_DIEPMSK_TxFIFOEmpty;
++ }
+ }
+
+ writel(clear, hsotg->regs + epint_reg);
+@@ -2280,6 +2299,12 @@ static int s3c_hsotg_ep_enable(struct us
+ break;
+ }
+
++ /* if the hardware has dedicated fifos, we must give each IN EP
++ * a unique tx-fifo even if it is non-periodic.
++ */
++ if (dir_in && hsotg->dedicated_fifos)
++ epctrl |= S3C_DxEPCTL_TxFNum(index);
++
+ /* for non control endpoints, set PID to D0 */
+ if (index)
+ epctrl |= S3C_DxEPCTL_SetD0PID;
+@@ -2569,7 +2594,8 @@ int usb_gadget_register_driver(struct us
+
+ writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
+ S3C_DIEPMSK_INTknEPMisMsk |
+- S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
++ S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
++ ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
+ hsotg->regs + S3C_DIEPMSK);
+
+ /* don't need XferCompl, we get that from RXFIFO in slave mode. In
+@@ -2778,6 +2804,8 @@ static void s3c_hsotg_otgreset(struct s3
+
+ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
+ {
++ u32 cfg4;
++
+ /* unmask subset of endpoint interrupts */
+
+ writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
+@@ -2813,6 +2841,14 @@ static void s3c_hsotg_init(struct s3c_hs
+
+ writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
+ hsotg->regs + S3C_GAHBCFG);
++
++ /* check hardware configuration */
++
++ cfg4 = readl(hsotg->regs + 0x50);
++ hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
++
++ dev_info(hsotg->dev, "%s fifos\n",
++ hsotg->dedicated_fifos ? "dedicated" : "shared");
+ }
+
+ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
diff --git a/usb/usb-s3c-hsotg-add-support-for-clock-gating.patch b/usb/usb-s3c-hsotg-add-support-for-clock-gating.patch
new file mode 100644
index 00000000000000..546f52dc54e33e
--- /dev/null
+++ b/usb/usb-s3c-hsotg-add-support-for-clock-gating.patch
@@ -0,0 +1,91 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 16:53:11 2010
+Date: Mon, 19 Jul 2010 16:01:42 +0200
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+Subject: USB: s3c-hsotg: add support for clock gating
+To: linux-usb@vger.kernel.org, linux-samsung-soc@vger.kernel.org
+Cc: m.szyprowski@samsung.com, kyungmin.park@samsung.com,
+ ben-linux@fluff.org, greg@kroah.com
+Message-id: <1279548102-32390-4-git-send-email-m.szyprowski@samsung.com>
+
+This patch adds support for clock gating of the HS/OTG block. On S5PV210
+otg gating clock is initally disabled so the driver needs to get and
+enable it before it can access its registers.
+
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -152,6 +152,7 @@ struct s3c_hsotg {
+ void __iomem *regs;
+ struct resource *regs_res;
+ int irq;
++ struct clk *clk;
+
+ unsigned int dedicated_fifos:1;
+
+@@ -3258,13 +3259,20 @@ static int __devinit s3c_hsotg_probe(str
+ hsotg->dev = dev;
+ hsotg->plat = plat;
+
++ hsotg->clk = clk_get(&pdev->dev, "otg");
++ if (IS_ERR(hsotg->clk)) {
++ dev_err(dev, "cannot get otg clock\n");
++ ret = -EINVAL;
++ goto err_mem;
++ }
++
+ platform_set_drvdata(pdev, hsotg);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "cannot find register resource 0\n");
+ ret = -EINVAL;
+- goto err_mem;
++ goto err_clk;
+ }
+
+ hsotg->regs_res = request_mem_region(res->start, resource_size(res),
+@@ -3272,7 +3280,7 @@ static int __devinit s3c_hsotg_probe(str
+ if (!hsotg->regs_res) {
+ dev_err(dev, "cannot reserve registers\n");
+ ret = -ENOENT;
+- goto err_mem;
++ goto err_clk;
+ }
+
+ hsotg->regs = ioremap(res->start, resource_size(res));
+@@ -3325,6 +3333,8 @@ static int __devinit s3c_hsotg_probe(str
+
+ /* reset the system */
+
++ clk_enable(hsotg->clk);
++
+ s3c_hsotg_gate(pdev, true);
+
+ s3c_hsotg_otgreset(hsotg);
+@@ -3348,7 +3358,8 @@ err_regs:
+ err_regs_res:
+ release_resource(hsotg->regs_res);
+ kfree(hsotg->regs_res);
+-
++err_clk:
++ clk_put(hsotg->clk);
+ err_mem:
+ kfree(hsotg);
+ return ret;
+@@ -3370,6 +3381,9 @@ static int __devexit s3c_hsotg_remove(st
+
+ s3c_hsotg_gate(pdev, false);
+
++ clk_disable(hsotg->clk);
++ clk_put(hsotg->clk);
++
+ kfree(hsotg);
+ return 0;
+ }
diff --git a/usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch b/usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch
new file mode 100644
index 00000000000000..3ed1117000d43d
--- /dev/null
+++ b/usb/usb-s3c-hsotg-add-support-for-external-usb-clock.patch
@@ -0,0 +1,68 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:50:30 2010
+From: Maurus Cuelenaere <mcuelenaere@gmail.com>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Maurus Cuelenaere <mcuelenaere@gmail.com>,
+ Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Add support for external USB clock
+Date: Mon, 19 Jul 2010 09:40:50 +0100
+Message-Id: <1279528850-28245-12-git-send-email-ben-linux@fluff.org>
+
+From: Maurus Cuelenaere <mcuelenaere@gmail.com>
+
+The PLL that drives the USB clock supports 3 input clocks: 12, 24 and 48Mhz.
+This patch adds support to the USB driver for setting the correct register bit
+according to the given clock.
+
+This depends on the following patch:
+[PATCH] ARM: S3C64XX: Add USB external clock definition
+
+Signed-off-by: Maurus Cuelenaere <mcuelenaere@gmail.com>
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -25,6 +25,7 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
++#include <linux/clk.h>
+
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
+@@ -2798,6 +2799,7 @@ static void __devinit s3c_hsotg_initep(s
+ */
+ static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
+ {
++ struct clk *xusbxti;
+ u32 osc;
+
+ writel(0, S3C_PHYPWR);
+@@ -2805,6 +2807,23 @@ static void s3c_hsotg_otgreset(struct s3
+
+ osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0;
+
++ xusbxti = clk_get(hsotg->dev, "xusbxti");
++ if (xusbxti && !IS_ERR(xusbxti)) {
++ switch (clk_get_rate(xusbxti)) {
++ case 12*MHZ:
++ osc |= S3C_PHYCLK_CLKSEL_12M;
++ break;
++ case 24*MHZ:
++ osc |= S3C_PHYCLK_CLKSEL_24M;
++ break;
++ default:
++ case 48*MHZ:
++ /* default reference clock */
++ break;
++ }
++ clk_put(xusbxti);
++ }
++
+ writel(osc | 0x10, S3C_PHYCLK);
+
+ /* issue a full set of resets to the otg and core */
diff --git a/usb/usb-s3c-hsotg-avoid-overwriting-contents-of-perodic-in-fifo.patch b/usb/usb-s3c-hsotg-avoid-overwriting-contents-of-perodic-in-fifo.patch
new file mode 100644
index 00000000000000..699fd2f9f8df31
--- /dev/null
+++ b/usb/usb-s3c-hsotg-avoid-overwriting-contents-of-perodic-in-fifo.patch
@@ -0,0 +1,51 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:05 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Avoid overwriting contents of perodic in 'fifo'
+Date: Mon, 19 Jul 2010 09:40:42 +0100
+Message-Id: <1279528850-28245-4-git-send-email-ben-linux@fluff.org>
+
+In shared fifo mode (used on older SoCs) the periodic in fifo beahves
+much more like a packet buffer, discarding old data when writing new
+data. Avoid this by ensuring that we do not load new transactions in
+when there is data sitting already in the FIFO.
+
+Note, this may not be an observed bug, we are fixing the case that this
+may happen.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -91,7 +91,9 @@ struct s3c_hsotg_req;
+ * For periodic IN endpoints, we have fifo_size and fifo_load to try
+ * and keep track of the amount of data in the periodic FIFO for each
+ * of these as we don't have a status register that tells us how much
+- * is in each of them.
++ * is in each of them. (note, this may actually be useless information
++ * as in shared-fifo mode periodic in acts like a single-frame packet
++ * buffer than a fifo)
+ */
+ struct s3c_hsotg_ep {
+ struct usb_ep ep;
+@@ -474,6 +476,14 @@ static int s3c_hsotg_write_fifo(struct s
+
+ size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+
++ /* if shared fifo, we cannot write anything until the
++ * previous data has been completely sent.
++ */
++ if (hs_ep->fifo_load != 0) {
++ s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
++ return -ENOSPC;
++ }
++
+ dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n",
+ __func__, size_left,
+ hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size);
diff --git a/usb/usb-s3c-hsotg-check-for-new-request-before-enqueing-new-setup.patch b/usb/usb-s3c-hsotg-check-for-new-request-before-enqueing-new-setup.patch
new file mode 100644
index 00000000000000..d9d2fbad74db99
--- /dev/null
+++ b/usb/usb-s3c-hsotg-check-for-new-request-before-enqueing-new-setup.patch
@@ -0,0 +1,34 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:46 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Check for new request before enqueing new setup
+Date: Mon, 19 Jul 2010 09:40:46 +0100
+Message-Id: <1279528850-28245-8-git-send-email-ben-linux@fluff.org>
+
+Before trying a new setup transaction after getting an EP0 in complete
+interrupt, check that the driver did not try and send more EP0 IN data
+before enqueing a new setup transaction.
+
+This fixes a bug where we cannot send all of the IN data in one go
+so split the transfer, but then fail to send all the data as we start
+waiting for a new OUT transaction
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -1790,7 +1790,7 @@ static void s3c_hsotg_epint(struct s3c_h
+ if (dir_in) {
+ s3c_hsotg_complete_in(hsotg, hs_ep);
+
+- if (idx == 0)
++ if (idx == 0 && !hs_ep->req)
+ s3c_hsotg_enqueue_setup(hsotg);
+ } else if (using_dma(hsotg)) {
+ /* We're using DMA, we need to fire an OutDone here
diff --git a/usb/usb-s3c-hsotg-fix-compilation-problem.patch b/usb/usb-s3c-hsotg-fix-compilation-problem.patch
new file mode 100644
index 00000000000000..2384ed103b4985
--- /dev/null
+++ b/usb/usb-s3c-hsotg-fix-compilation-problem.patch
@@ -0,0 +1,32 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 22 16:52:36 2010
+Date: Mon, 19 Jul 2010 16:01:40 +0200
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+Subject: USB: s3c-hsotg: fix compilation problem
+To: linux-usb@vger.kernel.org, linux-samsung-soc@vger.kernel.org
+Cc: m.szyprowski@samsung.com, kyungmin.park@samsung.com,
+ ben-linux@fluff.org, greg@kroah.com
+Message-id: <1279548102-32390-2-git-send-email-m.szyprowski@samsung.com>
+
+drivers/usb/gadget/s3c-hsotg.c: In function ‘s3c_hsotg_otgreset’:
+drivers/usb/gadget/s3c-hsotg.c:2816: error: ‘MHZ’ undeclared (first use in this function)
+drivers/usb/gadget/s3c-hsotg.c:2816: error: (Each undeclared identifier is reported only once
+drivers/usb/gadget/s3c-hsotg.c:2816: error: for each function it appears in.)
+
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -36,6 +36,7 @@
+ #include <plat/regs-usb-hsotg.h>
+ #include <mach/regs-sys.h>
+ #include <plat/udc-hs.h>
++#include <plat/cpu.h>
+
+ #define DMA_ADDR_INVALID (~((dma_addr_t)0))
+
diff --git a/usb/usb-s3c-hsotg-fix-max-ep0-in-request-length.patch b/usb/usb-s3c-hsotg-fix-max-ep0-in-request-length.patch
new file mode 100644
index 00000000000000..dd52da35379845
--- /dev/null
+++ b/usb/usb-s3c-hsotg-fix-max-ep0-in-request-length.patch
@@ -0,0 +1,30 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:57 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Fix max EP0 IN request length
+Date: Mon, 19 Jul 2010 09:40:47 +0100
+Message-Id: <1279528850-28245-9-git-send-email-ben-linux@fluff.org>
+
+The maximum length for any EP0 IN request on EP0 is 127 bytes, not 128
+as the driver currently has it.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -612,8 +612,7 @@ static unsigned get_ep_limit(struct s3c_
+ maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
+ } else {
+ if (hs_ep->dir_in) {
+- /* maxsize = S3C_DIEPTSIZ0_XferSize_LIMIT + 1; */
+- maxsize = 64+64+1;
++ maxsize = 64+64;
+ maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
+ } else {
+ maxsize = 0x3f;
diff --git a/usb/usb-s3c-hsotg-fix-out-packet-request-retry.patch b/usb/usb-s3c-hsotg-fix-out-packet-request-retry.patch
new file mode 100644
index 00000000000000..396ff6c8f161fd
--- /dev/null
+++ b/usb/usb-s3c-hsotg-fix-out-packet-request-retry.patch
@@ -0,0 +1,89 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:50:21 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Fix OUT packet request retry
+Date: Mon, 19 Jul 2010 09:40:49 +0100
+Message-Id: <1279528850-28245-11-git-send-email-ben-linux@fluff.org>
+
+If there is more data in the request than we could fit into a single
+hardware request, then check when the OutDone event is received if
+we have more data, and if so, schedule the new data instead of trying
+to complete the request (and in the case of EP0, sending a 0 packet
+in the middle of a transfer).
+
+Also, move the debug message about the current transfer state before
+the warning about a bad transfer.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -1383,6 +1383,9 @@ static void s3c_hsotg_rx_data(struct s3c
+ read_ptr = hs_req->req.actual;
+ max_req = hs_req->req.length - read_ptr;
+
++ dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
++ __func__, to_read, max_req, read_ptr, hs_req->req.length);
++
+ if (to_read > max_req) {
+ /* more data appeared than we where willing
+ * to deal with in this request.
+@@ -1392,9 +1395,6 @@ static void s3c_hsotg_rx_data(struct s3c
+ WARN_ON_ONCE(1);
+ }
+
+- dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
+- __func__, to_read, max_req, read_ptr, hs_req->req.length);
+-
+ hs_ep->total_data += to_read;
+ hs_req->req.actual += to_read;
+ to_read = DIV_ROUND_UP(to_read, 4);
+@@ -1463,9 +1463,11 @@ static void s3c_hsotg_send_zlp(struct s3
+ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
+ int epnum, bool was_setup)
+ {
++ u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
+ struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
+ struct s3c_hsotg_req *hs_req = hs_ep->req;
+ struct usb_request *req = &hs_req->req;
++ unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+ int result = 0;
+
+ if (!hs_req) {
+@@ -1474,9 +1476,7 @@ static void s3c_hsotg_handle_outdone(str
+ }
+
+ if (using_dma(hsotg)) {
+- u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
+ unsigned size_done;
+- unsigned size_left;
+
+ /* Calculate the size of the transfer by checking how much
+ * is left in the endpoint size register and then working it
+@@ -1486,14 +1486,18 @@ static void s3c_hsotg_handle_outdone(str
+ * so may overshoot/undershoot the transfer.
+ */
+
+- size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+-
+ size_done = hs_ep->size_loaded - size_left;
+ size_done += hs_ep->last_load;
+
+ req->actual = size_done;
+ }
+
++ /* if there is more request to do, schedule new transfer */
++ if (req->actual < req->length && size_left == 0) {
++ s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
++ return;
++ }
++
+ if (req->actual < req->length && req->short_not_ok) {
+ dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
+ __func__, req->actual, req->length);
diff --git a/usb/usb-s3c-hsotg-fix-the-out-ep0-limit.patch b/usb/usb-s3c-hsotg-fix-the-out-ep0-limit.patch
new file mode 100644
index 00000000000000..7d3bb7b4c9d887
--- /dev/null
+++ b/usb/usb-s3c-hsotg-fix-the-out-ep0-limit.patch
@@ -0,0 +1,32 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:50:10 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Fix the OUT EP0 limit
+Date: Mon, 19 Jul 2010 09:40:48 +0100
+Message-Id: <1279528850-28245-10-git-send-email-ben-linux@fluff.org>
+
+The EP0 out limit is the same as the IN limit, so make them the same.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -611,11 +611,10 @@ static unsigned get_ep_limit(struct s3c_
+ maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1;
+ maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
+ } else {
++ maxsize = 64+64;
+ if (hs_ep->dir_in) {
+- maxsize = 64+64;
+ maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
+ } else {
+- maxsize = 0x3f;
+ maxpkt = 2;
+ }
+ }
diff --git a/usb/usb-s3c-hsotg-increase-tx-fifo-limit.patch b/usb/usb-s3c-hsotg-increase-tx-fifo-limit.patch
new file mode 100644
index 00000000000000..3858476cc2c4fd
--- /dev/null
+++ b/usb/usb-s3c-hsotg-increase-tx-fifo-limit.patch
@@ -0,0 +1,45 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:48:45 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Increase TX fifo limit
+Date: Mon, 19 Jul 2010 09:40:40 +0100
+Message-Id: <1279528850-28245-2-git-send-email-ben-linux@fluff.org>
+
+Up the FIFO size for the TX to 1024 entries, as this now seems to work
+with all the cores. This fixes a problem when using large packets on
+a core with MPS set to 512 can hang due to insufficient space for the
+writes.
+
+The hang arises due to getting the non-periodic FIFO empty IRQ but
+not being able to satisfy any requests since there is never enough
+space to write 512 bytes into the buffer. This means we end up with
+a stream of interrupt requests.
+
+It is easier to up the TX FIFO to fill the space we left for it
+than to try and fix the positions in the code where we should have
+limited the max-packet size to < TXFIFOSIZE, since the TXFIFOSIZE
+depends on how the TX FIFOs have been setup.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/gadget/s3c-hsotg.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -310,11 +310,11 @@ static void s3c_hsotg_init_fifo(struct s
+ hsotg->regs + S3C_GNPTXFSIZ);
+ */
+
+- /* set FIFO sizes to 2048/0x1C0 */
++ /* set FIFO sizes to 2048/1024 */
+
+ writel(2048, hsotg->regs + S3C_GRXFSIZ);
+ writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
+- S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
++ S3C_GNPTXFSIZ_NPTxFDep(1024),
+ hsotg->regs + S3C_GNPTXFSIZ);
+
+ /* arange all the rest of the TX FIFOs, as some versions of this
diff --git a/usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch b/usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch
new file mode 100644
index 00000000000000..20dc6e133c112e
--- /dev/null
+++ b/usb/usb-s3c-hsotg-modify-only-selected-bits-in-s3c_phypwr-register.patch
@@ -0,0 +1,37 @@
+From m.szyprowski@samsung.com Thu Jul 22 16:52:55 2010
+Date: Mon, 19 Jul 2010 16:01:41 +0200
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+Subject: USB: s3c-hsotg: modify only selected bits in S3C_PHYPWR register
+To: linux-usb@vger.kernel.org, linux-samsung-soc@vger.kernel.org
+Cc: m.szyprowski@samsung.com, kyungmin.park@samsung.com, ben-linux@fluff.org,
+ greg@kroah.com
+Message-id: <1279548102-32390-3-git-send-email-m.szyprowski@samsung.com>
+
+S5PV210 SoCs has 2 USB PHY interfaces, both enabled by writing zero to
+S3C_PHYPWR register. HS/OTG driver uses only PHY0, so do not touch bits
+related to PHY1.
+
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -2801,9 +2801,11 @@ static void __devinit s3c_hsotg_initep(s
+ static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
+ {
+ struct clk *xusbxti;
+- u32 osc;
++ u32 pwr, osc;
+
+- writel(0, S3C_PHYPWR);
++ pwr = readl(S3C_PHYPWR);
++ pwr &= ~0x19;
++ writel(pwr, S3C_PHYPWR);
+ mdelay(1);
+
+ osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0;
diff --git a/usb/usb-s3c-hsotg-only-load-packet-per-fifo-write.patch b/usb/usb-s3c-hsotg-only-load-packet-per-fifo-write.patch
new file mode 100644
index 00000000000000..f60c81a3ea074f
--- /dev/null
+++ b/usb/usb-s3c-hsotg-only-load-packet-per-fifo-write.patch
@@ -0,0 +1,39 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:36 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Only load packet per fifo write
+Date: Mon, 19 Jul 2010 09:40:45 +0100
+Message-Id: <1279528850-28245-7-git-send-email-ben-linux@fluff.org>
+
+Limit the IN FIFO write to a single packet per attempt at writing,
+as per the specifications and ensure that we don't return fifo-full
+so that we can continue writing packets if we have the space.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -538,6 +538,17 @@ static int s3c_hsotg_write_fifo(struct s
+ if (can_write > 512)
+ can_write = 512;
+
++ /* limit the write to one max-packet size worth of data, but allow
++ * the transfer to return that it did not run out of fifo space
++ * doing it. */
++ if (to_write > hs_ep->ep.maxpacket) {
++ to_write = hs_ep->ep.maxpacket;
++
++ s3c_hsotg_en_gsint(hsotg,
++ periodic ? S3C_GINTSTS_PTxFEmp :
++ S3C_GINTSTS_NPTxFEmp);
++ }
++
+ /* see if we can write data */
+
+ if (to_write > can_write) {
diff --git a/usb/usb-s3c-hsotg-re-initialise-all-fifos-on-usb-bus-reset.patch b/usb/usb-s3c-hsotg-re-initialise-all-fifos-on-usb-bus-reset.patch
new file mode 100644
index 00000000000000..46dd1ac9060dd8
--- /dev/null
+++ b/usb/usb-s3c-hsotg-re-initialise-all-fifos-on-usb-bus-reset.patch
@@ -0,0 +1,44 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:49:16 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: Re-initialise all FIFOs on USB bus reset
+Date: Mon, 19 Jul 2010 09:40:43 +0100
+Message-Id: <1279528850-28245-5-git-send-email-ben-linux@fluff.org>
+
+The USB documentation suggest that the FIFOs should be reset when a
+bus reset event happens. Use the s3c_hsotg_init_fifo() to ensure that
+the FIFO layout is correct and that the FIFOs are flushed before
+acknowledging the reset.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -2082,17 +2082,12 @@ irq_retry:
+ kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
+
+ /* it seems after a reset we can end up with a situation
+- * where the TXFIFO still has data in it... try flushing
+- * it to remove anything that may still be in it.
++ * where the TXFIFO still has data in it... the docs
++ * suggest resetting all the fifos, so use the init_fifo
++ * code to relayout and flush the fifos.
+ */
+
+- if (1) {
+- writel(S3C_GRSTCTL_TxFNum(0) | S3C_GRSTCTL_TxFFlsh,
+- hsotg->regs + S3C_GRSTCTL);
+-
+- dev_info(hsotg->dev, "GNPTXSTS=%08x\n",
+- readl(hsotg->regs + S3C_GNPTXSTS));
+- }
++ s3c_hsotg_init_fifo(hsotg);
+
+ s3c_hsotg_enqueue_setup(hsotg);
+
diff --git a/usb/usb-s3c-hsotg-the-nptx-ptx-fifo-sizes-are-in-words-not-bytes.patch b/usb/usb-s3c-hsotg-the-nptx-ptx-fifo-sizes-are-in-words-not-bytes.patch
new file mode 100644
index 00000000000000..cf7fa79899e9e5
--- /dev/null
+++ b/usb/usb-s3c-hsotg-the-nptx-ptx-fifo-sizes-are-in-words-not-bytes.patch
@@ -0,0 +1,43 @@
+From ben@ben-laptop.fluff.org Thu Jul 22 16:48:54 2010
+From: Ben Dooks <ben-linux@fluff.org>
+To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org
+Cc: gregkh@suse.de, Ben Dooks <ben-linux@fluff.org>
+Subject: USB: s3c-hsotg: The NPTX/PTX FIFO sizes are in words, not bytes
+Date: Mon, 19 Jul 2010 09:40:41 +0100
+Message-Id: <1279528850-28245-3-git-send-email-ben-linux@fluff.org>
+
+Fix a problem where we have been underestimating the space available in
+the IN PTX/NPTX FIFOs by assuming that they where simply word aligned
+instead of in number-of-words. This means all length calculations need
+to be multiplied-by-4.
+
+Note, we do not change the information about fifo size or start addresses
+available to userspace as we assume the user can multiply by four easily
+and is already knows these values are in words.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/s3c-hsotg.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -505,6 +505,7 @@ static int s3c_hsotg_write_fifo(struct s
+ }
+
+ can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
++ can_write *= 4; /* fifo size is in 32bit quantities. */
+ }
+
+ dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
+@@ -2732,7 +2733,7 @@ static void __devinit s3c_hsotg_initep(s
+ */
+
+ ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum));
+- hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo);
++ hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
+
+ /* if we're using dma, we need to set the next-endpoint pointer
+ * to be something valid.
diff --git a/usb/usb-xhci-adds-new-cases-to-trb_comp_code-switch.patch b/usb/usb-xhci-adds-new-cases-to-trb_comp_code-switch.patch
new file mode 100644
index 00000000000000..561a7a8c7238bb
--- /dev/null
+++ b/usb/usb-xhci-adds-new-cases-to-trb_comp_code-switch.patch
@@ -0,0 +1,128 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:16:08 2010
+Date: Thu, 22 Jul 2010 15:23:20 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: adds new cases to trb_comp_code switch
+Message-ID: <20100722222320.GA21388@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch adds new cases to trb_comp_code switch, and moves
+the switch judgment ahead of fetching td.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 76 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 52 insertions(+), 24 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1605,36 +1605,16 @@ static int handle_tx_event(struct xhci_h
+ ep = &xdev->eps[ep_index];
+ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+- if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
++ if (!ep_ring ||
++ (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+ xhci_err(xhci, "ERROR Transfer event for disabled endpoint "
+ "or incorrect stream ring\n");
+ return -ENODEV;
+ }
+
+ event_dma = event->buffer;
+- /* This TRB should be in the TD at the head of this ring's TD list */
+- if (list_empty(&ep_ring->td_list)) {
+- xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+- TRB_TO_SLOT_ID(event->flags), ep_index);
+- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+- (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+- xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+- goto cleanup;
+- }
+- td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
+-
+- /* Is this a TRB in the currently executing TD? */
+- event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
+- td->last_trb, event_dma);
+- if (!event_seg) {
+- /* HC is busted, give up! */
+- xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
+- return -ESHUTDOWN;
+- }
+- event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
+-
+- /* Look for common error cases */
+ trb_comp_code = GET_COMP_CODE(event->transfer_len);
++ /* Look for common error cases */
+ switch (trb_comp_code) {
+ /* Skip codes that require special handling depending on
+ * transfer type
+@@ -1670,14 +1650,62 @@ static int handle_tx_event(struct xhci_h
+ xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
+ status = -ENOSR;
+ break;
++ case COMP_BW_OVER:
++ xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n");
++ break;
++ case COMP_BUFF_OVER:
++ xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n");
++ break;
++ case COMP_UNDERRUN:
++ /*
++ * When the Isoch ring is empty, the xHC will generate
++ * a Ring Overrun Event for IN Isoch endpoint or Ring
++ * Underrun Event for OUT Isoch endpoint.
++ */
++ xhci_dbg(xhci, "underrun event on endpoint\n");
++ if (!list_empty(&ep_ring->td_list))
++ xhci_dbg(xhci, "Underrun Event for slot %d ep %d "
++ "still with TDs queued?\n",
++ TRB_TO_SLOT_ID(event->flags), ep_index);
++ goto cleanup;
++ case COMP_OVERRUN:
++ xhci_dbg(xhci, "overrun event on endpoint\n");
++ if (!list_empty(&ep_ring->td_list))
++ xhci_dbg(xhci, "Overrun Event for slot %d ep %d "
++ "still with TDs queued?\n",
++ TRB_TO_SLOT_ID(event->flags), ep_index);
++ goto cleanup;
+ default:
+ if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
+ status = 0;
+ break;
+ }
+- xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n");
++ xhci_warn(xhci, "ERROR Unknown event condition, HC probably "
++ "busted\n");
++ goto cleanup;
++ }
++
++ /* This TRB should be in the TD at the head of this ring's TD list */
++ if (list_empty(&ep_ring->td_list)) {
++ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
++ TRB_TO_SLOT_ID(event->flags), ep_index);
++ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
++ (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
++ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+ goto cleanup;
+ }
++ td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
++
++ /* Is this a TRB in the currently executing TD? */
++ event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
++ td->last_trb, event_dma);
++ if (!event_seg) {
++ /* HC is busted, give up! */
++ xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
++ return -ESHUTDOWN;
++ }
++ event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
++
+ /* Now update the urb's actual_length and give back to the core */
+ /* Was this a control transfer? */
+ if (usb_endpoint_xfer_control(&td->urb->ep->desc))
diff --git a/usb/usb-xhci-allocate-bigger-ring-for-isochronous-endpoint.patch b/usb/usb-xhci-allocate-bigger-ring-for-isochronous-endpoint.patch
new file mode 100644
index 00000000000000..feb224e065b619
--- /dev/null
+++ b/usb/usb-xhci-allocate-bigger-ring-for-isochronous-endpoint.patch
@@ -0,0 +1,51 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:18:20 2010
+Date: Thu, 22 Jul 2010 15:23:47 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: allocate bigger ring for isochronous endpoint
+Message-ID: <20100722222347.GA21656@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+Isochronous endpoint needs a bigger size of transfer ring. Isochronous URB
+consists of multiple packets, each packet needs a isoc td to carry, and
+there will be multiple trbs inserted to the ring at one time. One segment
+is too small for isochronous endpoints, and it will result in
+room_on_ring() check failure and the URB is failed to enqueue.
+
+Allocate bigger ring for isochronous endpoint. 8 segments should be enough.
+This will be replaced with dynamic ring expansion in the future.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1112,8 +1112,18 @@ int xhci_endpoint_init(struct xhci_hcd *
+ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
+
+ /* Set up the endpoint ring */
+- virt_dev->eps[ep_index].new_ring =
+- xhci_ring_alloc(xhci, 1, true, mem_flags);
++ /*
++ * Isochronous endpoint ring needs bigger size because one isoc URB
++ * carries multiple packets and it will insert multiple tds to the
++ * ring.
++ * This should be replaced with dynamic ring resizing in the future.
++ */
++ if (usb_endpoint_xfer_isoc(&ep->desc))
++ virt_dev->eps[ep_index].new_ring =
++ xhci_ring_alloc(xhci, 8, true, mem_flags);
++ else
++ virt_dev->eps[ep_index].new_ring =
++ xhci_ring_alloc(xhci, 1, true, mem_flags);
+ if (!virt_dev->eps[ep_index].new_ring) {
+ /* Attempt to use the ring cache */
+ if (virt_dev->num_rings_cached == 0)
diff --git a/usb/usb-xhci-handle_tx_event-refactor-finish_td.patch b/usb/usb-xhci-handle_tx_event-refactor-finish_td.patch
new file mode 100644
index 00000000000000..5bc924c9eb78fe
--- /dev/null
+++ b/usb/usb-xhci-handle_tx_event-refactor-finish_td.patch
@@ -0,0 +1,270 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:14:29 2010
+Date: Thu, 22 Jul 2010 15:22:55 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: handle_tx_event() refactor: finish_td
+Message-ID: <20100722222255.GA21215@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch moves the td universal processing part in handle_tx_event()
+into a separate function finish_td().
+
+if finish_td() returns 1, it indicates the urb can be given back.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/host/xhci-ring.c | 185 ++++++++++++++++++++++++++-----------------
+ 1 file changed, 112 insertions(+), 73 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1258,6 +1258,104 @@ int xhci_is_vendor_info_code(struct xhci
+ }
+
+ /*
++ * Finish the td processing, remove the td from td list;
++ * Return 1 if the urb can be given back.
++ */
++static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
++ union xhci_trb *event_trb, struct xhci_transfer_event *event,
++ struct xhci_virt_ep *ep, int *status, bool skip)
++{
++ struct xhci_virt_device *xdev;
++ struct xhci_ring *ep_ring;
++ unsigned int slot_id;
++ int ep_index;
++ struct urb *urb = NULL;
++ struct xhci_ep_ctx *ep_ctx;
++ int ret = 0;
++ u32 trb_comp_code;
++
++ slot_id = TRB_TO_SLOT_ID(event->flags);
++ xdev = xhci->devs[slot_id];
++ ep_index = TRB_TO_EP_ID(event->flags) - 1;
++ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
++ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++ trb_comp_code = GET_COMP_CODE(event->transfer_len);
++
++ if (skip)
++ goto td_cleanup;
++
++ if (trb_comp_code == COMP_STOP_INVAL ||
++ trb_comp_code == COMP_STOP) {
++ /* The Endpoint Stop Command completion will take care of any
++ * stopped TDs. A stopped TD may be restarted, so don't update
++ * the ring dequeue pointer or take this TD off any lists yet.
++ */
++ ep->stopped_td = td;
++ ep->stopped_trb = event_trb;
++ return 0;
++ } else {
++ if (trb_comp_code == COMP_STALL) {
++ /* The transfer is completed from the driver's
++ * perspective, but we need to issue a set dequeue
++ * command for this stalled endpoint to move the dequeue
++ * pointer past the TD. We can't do that here because
++ * the halt condition must be cleared first. Let the
++ * USB class driver clear the stall later.
++ */
++ ep->stopped_td = td;
++ ep->stopped_trb = event_trb;
++ ep->stopped_stream = ep_ring->stream_id;
++ } else if (xhci_requires_manual_halt_cleanup(xhci,
++ ep_ctx, trb_comp_code)) {
++ /* Other types of errors halt the endpoint, but the
++ * class driver doesn't call usb_reset_endpoint() unless
++ * the error is -EPIPE. Clear the halted status in the
++ * xHCI hardware manually.
++ */
++ xhci_cleanup_halted_endpoint(xhci,
++ slot_id, ep_index, ep_ring->stream_id,
++ td, event_trb);
++ } else {
++ /* Update ring dequeue pointer */
++ while (ep_ring->dequeue != td->last_trb)
++ inc_deq(xhci, ep_ring, false);
++ inc_deq(xhci, ep_ring, false);
++ }
++
++td_cleanup:
++ /* Clean up the endpoint's TD list */
++ urb = td->urb;
++
++ /* Do one last check of the actual transfer length.
++ * If the host controller said we transferred more data than
++ * the buffer length, urb->actual_length will be a very big
++ * number (since it's unsigned). Play it safe and say we didn't
++ * transfer anything.
++ */
++ if (urb->actual_length > urb->transfer_buffer_length) {
++ xhci_warn(xhci, "URB transfer length is wrong, "
++ "xHC issue? req. len = %u, "
++ "act. len = %u\n",
++ urb->transfer_buffer_length,
++ urb->actual_length);
++ urb->actual_length = 0;
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ }
++ list_del(&td->td_list);
++ /* Was this TD slated to be cancelled but completed anyway? */
++ if (!list_empty(&td->cancelled_td_list))
++ list_del(&td->cancelled_td_list);
++
++ ret = 1;
++ }
++
++ return ret;
++}
++
++/*
+ * If this function returns an error condition, it means it got a Transfer
+ * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
+ * At this point, the host controller is probably hosed and should be reset.
+@@ -1278,6 +1376,7 @@ static int handle_tx_event(struct xhci_h
+ int status = -EINPROGRESS;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
++ int ret = 0;
+
+ xhci_dbg(xhci, "In %s\n", __func__);
+ slot_id = TRB_TO_SLOT_ID(event->flags);
+@@ -1308,7 +1407,6 @@ static int handle_tx_event(struct xhci_h
+ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+ (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+- urb = NULL;
+ goto cleanup;
+ }
+ xhci_dbg(xhci, "%s - getting list entry\n", __func__);
+@@ -1379,7 +1477,6 @@ static int handle_tx_event(struct xhci_h
+ break;
+ }
+ xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n");
+- urb = NULL;
+ goto cleanup;
+ }
+ /* Now update the urb's actual_length and give back to the core */
+@@ -1427,7 +1524,10 @@ static int handle_tx_event(struct xhci_h
+
+ xhci_cleanup_halted_endpoint(xhci,
+ slot_id, ep_index, 0, td, event_trb);
+- goto td_cleanup;
++
++ ret = finish_td(xhci, td, event_trb, event, ep,
++ &status, true);
++ goto cleanup;
+ }
+ /*
+ * Did we transfer any data, despite the errors that might have
+@@ -1456,7 +1556,6 @@ static int handle_tx_event(struct xhci_h
+ td->urb->transfer_buffer_length -
+ TRB_LEN(event->transfer_len);
+ xhci_dbg(xhci, "Waiting for status stage event\n");
+- urb = NULL;
+ goto cleanup;
+ }
+ }
+@@ -1558,68 +1657,16 @@ static int handle_tx_event(struct xhci_h
+ TRB_LEN(event->transfer_len);
+ }
+ }
+- if (trb_comp_code == COMP_STOP_INVAL ||
+- trb_comp_code == COMP_STOP) {
+- /* The Endpoint Stop Command completion will take care of any
+- * stopped TDs. A stopped TD may be restarted, so don't update
+- * the ring dequeue pointer or take this TD off any lists yet.
+- */
+- ep->stopped_td = td;
+- ep->stopped_trb = event_trb;
+- } else {
+- if (trb_comp_code == COMP_STALL) {
+- /* The transfer is completed from the driver's
+- * perspective, but we need to issue a set dequeue
+- * command for this stalled endpoint to move the dequeue
+- * pointer past the TD. We can't do that here because
+- * the halt condition must be cleared first. Let the
+- * USB class driver clear the stall later.
+- */
+- ep->stopped_td = td;
+- ep->stopped_trb = event_trb;
+- ep->stopped_stream = ep_ring->stream_id;
+- } else if (xhci_requires_manual_halt_cleanup(xhci,
+- ep_ctx, trb_comp_code)) {
+- /* Other types of errors halt the endpoint, but the
+- * class driver doesn't call usb_reset_endpoint() unless
+- * the error is -EPIPE. Clear the halted status in the
+- * xHCI hardware manually.
+- */
+- xhci_cleanup_halted_endpoint(xhci,
+- slot_id, ep_index, ep_ring->stream_id, td, event_trb);
+- } else {
+- /* Update ring dequeue pointer */
+- while (ep_ring->dequeue != td->last_trb)
+- inc_deq(xhci, ep_ring, false);
+- inc_deq(xhci, ep_ring, false);
+- }
+
+-td_cleanup:
+- /* Clean up the endpoint's TD list */
+- urb = td->urb;
+- /* Do one last check of the actual transfer length.
+- * If the host controller said we transferred more data than
+- * the buffer length, urb->actual_length will be a very big
+- * number (since it's unsigned). Play it safe and say we didn't
+- * transfer anything.
+- */
+- if (urb->actual_length > urb->transfer_buffer_length) {
+- xhci_warn(xhci, "URB transfer length is wrong, "
+- "xHC issue? req. len = %u, "
+- "act. len = %u\n",
+- urb->transfer_buffer_length,
+- urb->actual_length);
+- urb->actual_length = 0;
+- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- }
+- list_del(&td->td_list);
+- /* Was this TD slated to be cancelled but completed anyway? */
+- if (!list_empty(&td->cancelled_td_list))
+- list_del(&td->cancelled_td_list);
++ ret = finish_td(xhci, td, event_trb, event, ep, &status, false);
+
++cleanup:
++ inc_deq(xhci, xhci->event_ring, true);
++ xhci_set_hc_event_deq(xhci);
++
++ /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
++ if (ret) {
++ urb = td->urb;
+ /* Leave the TD around for the reset endpoint function to use
+ * (but only if it's not a control endpoint, since we already
+ * queued the Set TR dequeue pointer command for stalled
+@@ -1627,17 +1674,9 @@ td_cleanup:
+ */
+ if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+ (trb_comp_code != COMP_STALL &&
+- trb_comp_code != COMP_BABBLE)) {
++ trb_comp_code != COMP_BABBLE))
+ kfree(td);
+- }
+- urb->hcpriv = NULL;
+- }
+-cleanup:
+- inc_deq(xhci, xhci->event_ring, true);
+- xhci_set_hc_event_deq(xhci);
+
+- /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
+- if (urb) {
+ usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+ xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
+ urb, urb->actual_length, status);
diff --git a/usb/usb-xhci-handle_tx_event-refactor-process_bulk_intr_td.patch b/usb/usb-xhci-handle_tx_event-refactor-process_bulk_intr_td.patch
new file mode 100644
index 00000000000000..6447ef537dda65
--- /dev/null
+++ b/usb/usb-xhci-handle_tx_event-refactor-process_bulk_intr_td.patch
@@ -0,0 +1,255 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:15:37 2010
+Date: Thu, 22 Jul 2010 15:23:08 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB xHCI: handle_tx_event() refactor: process_bulk_intr_td
+Message-ID: <20100722222308.GA21286@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch moves the bulk and interrupt td processing part in
+handle_tx_event() into a separate function process_bulk_intr_td().
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/host/xhci-ring.c | 216 ++++++++++++++++++++++---------------------
+ 1 file changed, 115 insertions(+), 101 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1459,6 +1459,117 @@ static int process_ctrl_td(struct xhci_h
+ }
+
+ /*
++ * Process bulk and interrupt tds, update urb status and actual_length.
++ */
++static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
++ union xhci_trb *event_trb, struct xhci_transfer_event *event,
++ struct xhci_virt_ep *ep, int *status)
++{
++ struct xhci_ring *ep_ring;
++ union xhci_trb *cur_trb;
++ struct xhci_segment *cur_seg;
++ u32 trb_comp_code;
++
++ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
++ trb_comp_code = GET_COMP_CODE(event->transfer_len);
++
++ switch (trb_comp_code) {
++ case COMP_SUCCESS:
++ /* Double check that the HW transferred everything. */
++ if (event_trb != td->last_trb) {
++ xhci_warn(xhci, "WARN Successful completion "
++ "on short TX\n");
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ } else {
++ if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
++ xhci_dbg(xhci, "Successful bulk "
++ "transfer!\n");
++ else
++ xhci_dbg(xhci, "Successful interrupt "
++ "transfer!\n");
++ *status = 0;
++ }
++ break;
++ case COMP_SHORT_TX:
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ break;
++ default:
++ /* Others already handled above */
++ break;
++ }
++ dev_dbg(&td->urb->dev->dev,
++ "ep %#x - asked for %d bytes, "
++ "%d bytes untransferred\n",
++ td->urb->ep->desc.bEndpointAddress,
++ td->urb->transfer_buffer_length,
++ TRB_LEN(event->transfer_len));
++ /* Fast path - was this the last TRB in the TD for this URB? */
++ if (event_trb == td->last_trb) {
++ if (TRB_LEN(event->transfer_len) != 0) {
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length -
++ TRB_LEN(event->transfer_len);
++ if (td->urb->transfer_buffer_length <
++ td->urb->actual_length) {
++ xhci_warn(xhci, "HC gave bad length "
++ "of %d bytes left\n",
++ TRB_LEN(event->transfer_len));
++ td->urb->actual_length = 0;
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ }
++ /* Don't overwrite a previously set error code */
++ if (*status == -EINPROGRESS) {
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ }
++ } else {
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length;
++ /* Ignore a short packet completion if the
++ * untransferred length was zero.
++ */
++ if (*status == -EREMOTEIO)
++ *status = 0;
++ }
++ } else {
++ /* Slow path - walk the list, starting from the dequeue
++ * pointer, to get the actual length transferred.
++ */
++ td->urb->actual_length = 0;
++ for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
++ cur_trb != event_trb;
++ next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
++ if ((cur_trb->generic.field[3] &
++ TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
++ (cur_trb->generic.field[3] &
++ TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
++ td->urb->actual_length +=
++ TRB_LEN(cur_trb->generic.field[2]);
++ }
++ /* If the ring didn't stop on a Link or No-op TRB, add
++ * in the actual bytes transferred from the Normal TRB
++ */
++ if (trb_comp_code != COMP_STOP_INVAL)
++ td->urb->actual_length +=
++ TRB_LEN(cur_trb->generic.field[2]) -
++ TRB_LEN(event->transfer_len);
++ }
++
++ return finish_td(xhci, td, event_trb, event, ep, status, false);
++}
++
++/*
+ * If this function returns an error condition, it means it got a Transfer
+ * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
+ * At this point, the host controller is probably hosed and should be reset.
+@@ -1584,109 +1695,12 @@ static int handle_tx_event(struct xhci_h
+ }
+ /* Now update the urb's actual_length and give back to the core */
+ /* Was this a control transfer? */
+- if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
++ if (usb_endpoint_xfer_control(&td->urb->ep->desc))
+ ret = process_ctrl_td(xhci, td, event_trb, event, ep,
+ &status);
+- goto cleanup;
+- } else {
+- switch (trb_comp_code) {
+- case COMP_SUCCESS:
+- /* Double check that the HW transferred everything. */
+- if (event_trb != td->last_trb) {
+- xhci_warn(xhci, "WARN Successful completion "
+- "on short TX\n");
+- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- } else {
+- if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
+- xhci_dbg(xhci, "Successful bulk "
+- "transfer!\n");
+- else
+- xhci_dbg(xhci, "Successful interrupt "
+- "transfer!\n");
+- status = 0;
+- }
+- break;
+- case COMP_SHORT_TX:
+- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- break;
+- default:
+- /* Others already handled above */
+- break;
+- }
+- dev_dbg(&td->urb->dev->dev,
+- "ep %#x - asked for %d bytes, "
+- "%d bytes untransferred\n",
+- td->urb->ep->desc.bEndpointAddress,
+- td->urb->transfer_buffer_length,
+- TRB_LEN(event->transfer_len));
+- /* Fast path - was this the last TRB in the TD for this URB? */
+- if (event_trb == td->last_trb) {
+- if (TRB_LEN(event->transfer_len) != 0) {
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length -
+- TRB_LEN(event->transfer_len);
+- if (td->urb->transfer_buffer_length <
+- td->urb->actual_length) {
+- xhci_warn(xhci, "HC gave bad length "
+- "of %d bytes left\n",
+- TRB_LEN(event->transfer_len));
+- td->urb->actual_length = 0;
+- if (td->urb->transfer_flags &
+- URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- }
+- /* Don't overwrite a previously set error code */
+- if (status == -EINPROGRESS) {
+- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- }
+- } else {
+- td->urb->actual_length = td->urb->transfer_buffer_length;
+- /* Ignore a short packet completion if the
+- * untransferred length was zero.
+- */
+- if (status == -EREMOTEIO)
+- status = 0;
+- }
+- } else {
+- /* Slow path - walk the list, starting from the dequeue
+- * pointer, to get the actual length transferred.
+- */
+- union xhci_trb *cur_trb;
+- struct xhci_segment *cur_seg;
+-
+- td->urb->actual_length = 0;
+- for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
+- cur_trb != event_trb;
+- next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
+- if ((cur_trb->generic.field[3] &
+- TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
+- (cur_trb->generic.field[3] &
+- TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
+- td->urb->actual_length +=
+- TRB_LEN(cur_trb->generic.field[2]);
+- }
+- /* If the ring didn't stop on a Link or No-op TRB, add
+- * in the actual bytes transferred from the Normal TRB
+- */
+- if (trb_comp_code != COMP_STOP_INVAL)
+- td->urb->actual_length +=
+- TRB_LEN(cur_trb->generic.field[2]) -
+- TRB_LEN(event->transfer_len);
+- }
+- }
+-
+- ret = finish_td(xhci, td, event_trb, event, ep, &status, false);
++ else
++ ret = process_bulk_intr_td(xhci, td, event_trb, event, ep,
++ &status);
+
+ cleanup:
+ inc_deq(xhci, xhci->event_ring, true);
diff --git a/usb/usb-xhci-handle_tx_event-refactor-process_ctrl_td.patch b/usb/usb-xhci-handle_tx_event-refactor-process_ctrl_td.patch
new file mode 100644
index 00000000000000..ff71ed728f396c
--- /dev/null
+++ b/usb/usb-xhci-handle_tx_event-refactor-process_ctrl_td.patch
@@ -0,0 +1,222 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:14:54 2010
+Date: Thu, 22 Jul 2010 15:23:03 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: handle_tx_event() refactor: process_ctrl_td
+Message-ID: <20100722222303.GA21251@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch moves the ctrl td processing part in handle_tx_event()
+into a separate function process_ctrl_td().
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 184 ++++++++++++++++++++++++-------------------
+ 1 file changed, 106 insertions(+), 78 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1356,6 +1356,109 @@ td_cleanup:
+ }
+
+ /*
++ * Process control tds, update urb status and actual_length.
++ */
++static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
++ union xhci_trb *event_trb, struct xhci_transfer_event *event,
++ struct xhci_virt_ep *ep, int *status)
++{
++ struct xhci_virt_device *xdev;
++ struct xhci_ring *ep_ring;
++ unsigned int slot_id;
++ int ep_index;
++ struct xhci_ep_ctx *ep_ctx;
++ u32 trb_comp_code;
++
++ slot_id = TRB_TO_SLOT_ID(event->flags);
++ xdev = xhci->devs[slot_id];
++ ep_index = TRB_TO_EP_ID(event->flags) - 1;
++ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
++ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++ trb_comp_code = GET_COMP_CODE(event->transfer_len);
++
++ xhci_debug_trb(xhci, xhci->event_ring->dequeue);
++ switch (trb_comp_code) {
++ case COMP_SUCCESS:
++ if (event_trb == ep_ring->dequeue) {
++ xhci_warn(xhci, "WARN: Success on ctrl setup TRB "
++ "without IOC set??\n");
++ *status = -ESHUTDOWN;
++ } else if (event_trb != td->last_trb) {
++ xhci_warn(xhci, "WARN: Success on ctrl data TRB "
++ "without IOC set??\n");
++ *status = -ESHUTDOWN;
++ } else {
++ xhci_dbg(xhci, "Successful control transfer!\n");
++ *status = 0;
++ }
++ break;
++ case COMP_SHORT_TX:
++ xhci_warn(xhci, "WARN: short transfer on control ep\n");
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ *status = -EREMOTEIO;
++ else
++ *status = 0;
++ break;
++ default:
++ if (!xhci_requires_manual_halt_cleanup(xhci,
++ ep_ctx, trb_comp_code))
++ break;
++ xhci_dbg(xhci, "TRB error code %u, "
++ "halted endpoint index = %u\n",
++ trb_comp_code, ep_index);
++ /* else fall through */
++ case COMP_STALL:
++ /* Did we transfer part of the data (middle) phase? */
++ if (event_trb != ep_ring->dequeue &&
++ event_trb != td->last_trb)
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length
++ - TRB_LEN(event->transfer_len);
++ else
++ td->urb->actual_length = 0;
++
++ xhci_cleanup_halted_endpoint(xhci,
++ slot_id, ep_index, 0, td, event_trb);
++ return finish_td(xhci, td, event_trb, event, ep, status, true);
++ }
++ /*
++ * Did we transfer any data, despite the errors that might have
++ * happened? I.e. did we get past the setup stage?
++ */
++ if (event_trb != ep_ring->dequeue) {
++ /* The event was for the status stage */
++ if (event_trb == td->last_trb) {
++ if (td->urb->actual_length != 0) {
++ /* Don't overwrite a previously set error code
++ */
++ if ((*status == -EINPROGRESS || *status == 0) &&
++ (td->urb->transfer_flags
++ & URB_SHORT_NOT_OK))
++ /* Did we already see a short data
++ * stage? */
++ *status = -EREMOTEIO;
++ } else {
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length;
++ }
++ } else {
++ /* Maybe the event was for the data stage? */
++ if (trb_comp_code != COMP_STOP_INVAL) {
++ /* We didn't stop on a link TRB in the middle */
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length -
++ TRB_LEN(event->transfer_len);
++ xhci_dbg(xhci, "Waiting for status "
++ "stage event\n");
++ return 0;
++ }
++ }
++ }
++
++ return finish_td(xhci, td, event_trb, event, ep, status, false);
++}
++
++/*
+ * If this function returns an error condition, it means it got a Transfer
+ * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
+ * At this point, the host controller is probably hosed and should be reset.
+@@ -1482,84 +1585,9 @@ static int handle_tx_event(struct xhci_h
+ /* Now update the urb's actual_length and give back to the core */
+ /* Was this a control transfer? */
+ if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
+- xhci_debug_trb(xhci, xhci->event_ring->dequeue);
+- switch (trb_comp_code) {
+- case COMP_SUCCESS:
+- if (event_trb == ep_ring->dequeue) {
+- xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
+- status = -ESHUTDOWN;
+- } else if (event_trb != td->last_trb) {
+- xhci_warn(xhci, "WARN: Success on ctrl data TRB without IOC set??\n");
+- status = -ESHUTDOWN;
+- } else {
+- xhci_dbg(xhci, "Successful control transfer!\n");
+- status = 0;
+- }
+- break;
+- case COMP_SHORT_TX:
+- xhci_warn(xhci, "WARN: short transfer on control ep\n");
+- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+- status = -EREMOTEIO;
+- else
+- status = 0;
+- break;
+-
+- default:
+- if (!xhci_requires_manual_halt_cleanup(xhci,
+- ep_ctx, trb_comp_code))
+- break;
+- xhci_dbg(xhci, "TRB error code %u, "
+- "halted endpoint index = %u\n",
+- trb_comp_code, ep_index);
+- /* else fall through */
+- case COMP_STALL:
+- /* Did we transfer part of the data (middle) phase? */
+- if (event_trb != ep_ring->dequeue &&
+- event_trb != td->last_trb)
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length
+- - TRB_LEN(event->transfer_len);
+- else
+- td->urb->actual_length = 0;
+-
+- xhci_cleanup_halted_endpoint(xhci,
+- slot_id, ep_index, 0, td, event_trb);
+-
+- ret = finish_td(xhci, td, event_trb, event, ep,
+- &status, true);
+- goto cleanup;
+- }
+- /*
+- * Did we transfer any data, despite the errors that might have
+- * happened? I.e. did we get past the setup stage?
+- */
+- if (event_trb != ep_ring->dequeue) {
+- /* The event was for the status stage */
+- if (event_trb == td->last_trb) {
+- if (td->urb->actual_length != 0) {
+- /* Don't overwrite a previously set error code */
+- if ((status == -EINPROGRESS ||
+- status == 0) &&
+- (td->urb->transfer_flags
+- & URB_SHORT_NOT_OK))
+- /* Did we already see a short data stage? */
+- status = -EREMOTEIO;
+- } else {
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length;
+- }
+- } else {
+- /* Maybe the event was for the data stage? */
+- if (trb_comp_code != COMP_STOP_INVAL) {
+- /* We didn't stop on a link TRB in the middle */
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length -
+- TRB_LEN(event->transfer_len);
+- xhci_dbg(xhci, "Waiting for status stage event\n");
+- goto cleanup;
+- }
+- }
+- }
++ ret = process_ctrl_td(xhci, td, event_trb, event, ep,
++ &status);
++ goto cleanup;
+ } else {
+ switch (trb_comp_code) {
+ case COMP_SUCCESS:
diff --git a/usb/usb-xhci-introduce-urb_priv-structure.patch b/usb/usb-xhci-introduce-urb_priv-structure.patch
new file mode 100644
index 00000000000000..c46c9dc796911e
--- /dev/null
+++ b/usb/usb-xhci-introduce-urb_priv-structure.patch
@@ -0,0 +1,397 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:17:16 2010
+Date: Thu, 22 Jul 2010 15:23:31 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: Introduce urb_priv structure
+Message-ID: <20100722222331.GA21527@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+Add urb_priv data structure to xHCI driver. This structure allows multiple
+xhci TDs to be linked to one urb, which is essential for isochronous
+transfer. For non-isochronous urb, only one TD is needed for one urb;
+for isochronous urb, the TD number for the urb is equal to
+urb->number_of_packets.
+
+The length field of urb_priv indicates the number of TDs in the urb.
+The td_cnt field indicates the number of TDs already processed by xHC.
+When td_cnt matches length, the urb can be given back to usbcore.
+
+When an urb is dequeued or cancelled, add all the unprocessed TDs to the
+endpoint's cancelled_td_list. When process a cancelled TD, increase
+td_cnt field. When td_cnt equals urb_priv->length, giveback the
+cancelled urb.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/host/xhci-mem.c | 16 +++++++
+ drivers/usb/host/xhci-ring.c | 91 +++++++++++++++++++++++++++++--------------
+ drivers/usb/host/xhci.c | 45 ++++++++++++++++++---
+ drivers/usb/host/xhci.h | 7 +++
+ 4 files changed, 125 insertions(+), 34 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1390,6 +1390,22 @@ struct xhci_command *xhci_alloc_command(
+ return command;
+ }
+
++void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv)
++{
++ int last;
++
++ if (!urb_priv)
++ return;
++
++ last = urb_priv->length - 1;
++ if (last >= 0) {
++ int i;
++ for (i = 0; i <= last; i++)
++ kfree(urb_priv->td[i]);
++ }
++ kfree(urb_priv);
++}
++
+ void xhci_free_command(struct xhci_hcd *xhci,
+ struct xhci_command *command)
+ {
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -578,16 +578,24 @@ static void xhci_giveback_urb_in_irq(str
+ struct xhci_td *cur_td, int status, char *adjective)
+ {
+ struct usb_hcd *hcd = xhci_to_hcd(xhci);
++ struct urb *urb;
++ struct urb_priv *urb_priv;
+
+- cur_td->urb->hcpriv = NULL;
+- usb_hcd_unlink_urb_from_ep(hcd, cur_td->urb);
+- xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, cur_td->urb);
++ urb = cur_td->urb;
++ urb_priv = urb->hcpriv;
++ urb_priv->td_cnt++;
++
++ /* Only giveback urb when this is the last td in urb */
++ if (urb_priv->td_cnt == urb_priv->length) {
++ usb_hcd_unlink_urb_from_ep(hcd, urb);
++ xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, urb);
+
+- spin_unlock(&xhci->lock);
+- usb_hcd_giveback_urb(hcd, cur_td->urb, status);
+- kfree(cur_td);
+- spin_lock(&xhci->lock);
+- xhci_dbg(xhci, "%s URB given back\n", adjective);
++ spin_unlock(&xhci->lock);
++ usb_hcd_giveback_urb(hcd, urb, status);
++ xhci_urb_free_priv(xhci, urb_priv);
++ spin_lock(&xhci->lock);
++ xhci_dbg(xhci, "%s URB given back\n", adjective);
++ }
+ }
+
+ /*
+@@ -1272,6 +1280,7 @@ static int finish_td(struct xhci_hcd *xh
+ struct urb *urb = NULL;
+ struct xhci_ep_ctx *ep_ctx;
+ int ret = 0;
++ struct urb_priv *urb_priv;
+ u32 trb_comp_code;
+
+ slot_id = TRB_TO_SLOT_ID(event->flags);
+@@ -1325,6 +1334,7 @@ static int finish_td(struct xhci_hcd *xh
+ td_cleanup:
+ /* Clean up the endpoint's TD list */
+ urb = td->urb;
++ urb_priv = urb->hcpriv;
+
+ /* Do one last check of the actual transfer length.
+ * If the host controller said we transferred more data than
+@@ -1349,7 +1359,10 @@ td_cleanup:
+ if (!list_empty(&td->cancelled_td_list))
+ list_del(&td->cancelled_td_list);
+
+- ret = 1;
++ urb_priv->td_cnt++;
++ /* Giveback the urb when all the tds are completed */
++ if (urb_priv->td_cnt == urb_priv->length)
++ ret = 1;
+ }
+
+ return ret;
+@@ -1588,6 +1601,7 @@ static int handle_tx_event(struct xhci_h
+ union xhci_trb *event_trb;
+ struct urb *urb = NULL;
+ int status = -EINPROGRESS;
++ struct urb_priv *urb_priv;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
+ int ret = 0;
+@@ -1770,6 +1784,7 @@ cleanup:
+
+ if (ret) {
+ urb = td->urb;
++ urb_priv = urb->hcpriv;
+ /* Leave the TD around for the reset endpoint function
+ * to use(but only if it's not a control endpoint,
+ * since we already queued the Set TR dequeue pointer
+@@ -1778,7 +1793,7 @@ cleanup:
+ if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+ (trb_comp_code != COMP_STALL &&
+ trb_comp_code != COMP_BABBLE))
+- kfree(td);
++ xhci_urb_free_priv(xhci, urb_priv);
+
+ usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+ xhci_dbg(xhci, "Giveback URB %p, len = %d, "
+@@ -1979,10 +1994,12 @@ static int prepare_transfer(struct xhci_
+ unsigned int stream_id,
+ unsigned int num_trbs,
+ struct urb *urb,
+- struct xhci_td **td,
++ unsigned int td_index,
+ gfp_t mem_flags)
+ {
+ int ret;
++ struct urb_priv *urb_priv;
++ struct xhci_td *td;
+ struct xhci_ring *ep_ring;
+ struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+
+@@ -1998,24 +2015,29 @@ static int prepare_transfer(struct xhci_
+ num_trbs, mem_flags);
+ if (ret)
+ return ret;
+- *td = kzalloc(sizeof(struct xhci_td), mem_flags);
+- if (!*td)
+- return -ENOMEM;
+- INIT_LIST_HEAD(&(*td)->td_list);
+- INIT_LIST_HEAD(&(*td)->cancelled_td_list);
+
+- ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
+- if (unlikely(ret)) {
+- kfree(*td);
+- return ret;
++ urb_priv = urb->hcpriv;
++ td = urb_priv->td[td_index];
++
++ INIT_LIST_HEAD(&td->td_list);
++ INIT_LIST_HEAD(&td->cancelled_td_list);
++
++ if (td_index == 0) {
++ ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
++ if (unlikely(ret)) {
++ xhci_urb_free_priv(xhci, urb_priv);
++ urb->hcpriv = NULL;
++ return ret;
++ }
+ }
+
+- (*td)->urb = urb;
+- urb->hcpriv = (void *) (*td);
++ td->urb = urb;
+ /* Add this TD to the tail of the endpoint ring's TD list */
+- list_add_tail(&(*td)->td_list, &ep_ring->td_list);
+- (*td)->start_seg = ep_ring->enq_seg;
+- (*td)->first_trb = ep_ring->enqueue;
++ list_add_tail(&td->td_list, &ep_ring->td_list);
++ td->start_seg = ep_ring->enq_seg;
++ td->first_trb = ep_ring->enqueue;
++
++ urb_priv->td[td_index] = td;
+
+ return 0;
+ }
+@@ -2154,6 +2176,7 @@ static int queue_bulk_sg_tx(struct xhci_
+ {
+ struct xhci_ring *ep_ring;
+ unsigned int num_trbs;
++ struct urb_priv *urb_priv;
+ struct xhci_td *td;
+ struct scatterlist *sg;
+ int num_sgs;
+@@ -2174,9 +2197,13 @@ static int queue_bulk_sg_tx(struct xhci_
+
+ trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+- num_trbs, urb, &td, mem_flags);
++ num_trbs, urb, 0, mem_flags);
+ if (trb_buff_len < 0)
+ return trb_buff_len;
++
++ urb_priv = urb->hcpriv;
++ td = urb_priv->td[0];
++
+ /*
+ * Don't give the first TRB to the hardware (by toggling the cycle bit)
+ * until we've finished creating all the other TRBs. The ring's cycle
+@@ -2297,6 +2324,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ struct urb *urb, int slot_id, unsigned int ep_index)
+ {
+ struct xhci_ring *ep_ring;
++ struct urb_priv *urb_priv;
+ struct xhci_td *td;
+ int num_trbs;
+ struct xhci_generic_trb *start_trb;
+@@ -2342,10 +2370,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+- num_trbs, urb, &td, mem_flags);
++ num_trbs, urb, 0, mem_flags);
+ if (ret < 0)
+ return ret;
+
++ urb_priv = urb->hcpriv;
++ td = urb_priv->td[0];
++
+ /*
+ * Don't give the first TRB to the hardware (by toggling the cycle bit)
+ * until we've finished creating all the other TRBs. The ring's cycle
+@@ -2431,6 +2462,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ struct xhci_generic_trb *start_trb;
+ int start_cycle;
+ u32 field, length_field;
++ struct urb_priv *urb_priv;
+ struct xhci_td *td;
+
+ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
+@@ -2458,10 +2490,13 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ num_trbs++;
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+- num_trbs, urb, &td, mem_flags);
++ num_trbs, urb, 0, mem_flags);
+ if (ret < 0)
+ return ret;
+
++ urb_priv = urb->hcpriv;
++ td = urb_priv->td[0];
++
+ /*
+ * Don't give the first TRB to the hardware (by toggling the cycle bit)
+ * until we've finished creating all the other TRBs. The ring's cycle
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -804,7 +804,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ unsigned long flags;
+ int ret = 0;
+ unsigned int slot_id, ep_index;
+-
++ struct urb_priv *urb_priv;
++ int size, i;
+
+ if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
+ return -EINVAL;
+@@ -824,6 +825,30 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ ret = -ESHUTDOWN;
+ goto exit;
+ }
++
++ if (usb_endpoint_xfer_isoc(&urb->ep->desc))
++ size = urb->number_of_packets;
++ else
++ size = 1;
++
++ urb_priv = kzalloc(sizeof(struct urb_priv) +
++ size * sizeof(struct xhci_td *), mem_flags);
++ if (!urb_priv)
++ return -ENOMEM;
++
++ for (i = 0; i < size; i++) {
++ urb_priv->td[i] = kzalloc(sizeof(struct xhci_td), mem_flags);
++ if (!urb_priv->td[i]) {
++ urb_priv->length = i;
++ xhci_urb_free_priv(xhci, urb_priv);
++ return -ENOMEM;
++ }
++ }
++
++ urb_priv->length = size;
++ urb_priv->td_cnt = 0;
++ urb->hcpriv = urb_priv;
++
+ if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+ /* Check to see if the max packet size for the default control
+ * endpoint changed during FS device enumeration
+@@ -877,6 +902,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ exit:
+ return ret;
+ dying:
++ xhci_urb_free_priv(xhci, urb_priv);
++ urb->hcpriv = NULL;
+ xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
+ "non-responsive xHCI host.\n",
+ urb->ep->desc.bEndpointAddress, urb);
+@@ -918,9 +945,10 @@ dying:
+ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ unsigned long flags;
+- int ret;
++ int ret, i;
+ u32 temp;
+ struct xhci_hcd *xhci;
++ struct urb_priv *urb_priv;
+ struct xhci_td *td;
+ unsigned int ep_index;
+ struct xhci_ring *ep_ring;
+@@ -935,12 +963,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+ temp = xhci_readl(xhci, &xhci->op_regs->status);
+ if (temp == 0xffffffff) {
+ xhci_dbg(xhci, "HW died, freeing TD.\n");
+- td = (struct xhci_td *) urb->hcpriv;
++ urb_priv = urb->hcpriv;
+
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
+- kfree(td);
++ xhci_urb_free_priv(xhci, urb_priv);
+ return ret;
+ }
+ if (xhci->xhc_state & XHCI_STATE_DYING) {
+@@ -968,9 +996,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+
+ xhci_dbg(xhci, "Endpoint ring:\n");
+ xhci_debug_ring(xhci, ep_ring);
+- td = (struct xhci_td *) urb->hcpriv;
+
+- list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
++ urb_priv = urb->hcpriv;
++
++ for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
++ td = urb_priv->td[i];
++ list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
++ }
++
+ /* Queue a stop endpoint command, but only if this is
+ * the first cancellation to be handled.
+ */
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1090,6 +1090,12 @@ struct xhci_scratchpad {
+ dma_addr_t *sp_dma_buffers;
+ };
+
++struct urb_priv {
++ int length;
++ int td_cnt;
++ struct xhci_td *td[0];
++};
++
+ /*
+ * Each segment table entry is 4*32bits long. 1K seems like an ok size:
+ * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
+@@ -1347,6 +1353,7 @@ struct xhci_ring *xhci_stream_id_to_ring
+ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
+ bool allocate_in_ctx, bool allocate_completion,
+ gfp_t mem_flags);
++void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv);
+ void xhci_free_command(struct xhci_hcd *xhci,
+ struct xhci_command *command);
+
diff --git a/usb/usb-xhci-isoc-urb-enqueue.patch b/usb/usb-xhci-isoc-urb-enqueue.patch
new file mode 100644
index 00000000000000..7db38ba9ba6f81
--- /dev/null
+++ b/usb/usb-xhci-isoc-urb-enqueue.patch
@@ -0,0 +1,37 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:18:44 2010
+Date: Thu, 22 Jul 2010 15:23:52 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: Isoc urb enqueue
+Message-ID: <20100722222352.GA21718@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+Enable isochronous urb enqueue.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -897,7 +897,12 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ slot_id, ep_index);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else {
+- ret = -EINVAL;
++ spin_lock_irqsave(&xhci->lock, flags);
++ if (xhci->xhc_state & XHCI_STATE_DYING)
++ goto dying;
++ ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
++ slot_id, ep_index);
++ spin_unlock_irqrestore(&xhci->lock, flags);
+ }
+ exit:
+ return ret;
diff --git a/usb/usb-xhci-isochronous-transfer-implementation.patch b/usb/usb-xhci-isochronous-transfer-implementation.patch
new file mode 100644
index 00000000000000..dc05da22983e2c
--- /dev/null
+++ b/usb/usb-xhci-isochronous-transfer-implementation.patch
@@ -0,0 +1,408 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:17:49 2010
+Date: Thu, 22 Jul 2010 15:23:39 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: Isochronous transfer implementation
+Message-ID: <20100722222339.GA21591@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch implements isochronous urb enqueue and interrupt handler part.
+
+When an isochronous urb is passed to xHCI driver, first check the transfer
+ring to guarantee there is enough room for the whole urb. Then update the
+start_frame and interval field of the urb. Always assume URB_ISO_ASAP
+is set, and never use urb->start_frame as input.
+
+The number of isoc TDs is equal to urb->number_of_packets. One isoc TD is
+consumed every Interval. Each isoc TD consists of an Isoch TRB chained to
+zero or more Normal TRBs.
+
+Call prepare_transfer for each TD to do initialization; then calculate the
+number of TRBs needed for each TD. If the data required by an isoc TD is
+physically contiguous (not crosses a page boundary), then only one isoc TRB
+is needed; otherwise one or more additional normal TRB shall be chained to
+the isoc TRB by the host.
+
+Set TRB_IOC to the last TRB of each isoc TD. Do not ring endpoint doorbell
+to start xHC procession until all the TDs are inserted to the endpoint
+transer ring.
+
+In irq handler, update urb status and actual_length, increase
+urb_priv->td_cnt. When all the TDs are completed(td_cnt is equal to
+urb_priv->length), giveback the urb to usbcore.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 319 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci.h | 5
+ 2 files changed, 324 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1472,6 +1472,104 @@ static int process_ctrl_td(struct xhci_h
+ }
+
+ /*
++ * Process isochronous tds, update urb packet status and actual_length.
++ */
++static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
++ union xhci_trb *event_trb, struct xhci_transfer_event *event,
++ struct xhci_virt_ep *ep, int *status)
++{
++ struct xhci_ring *ep_ring;
++ struct urb_priv *urb_priv;
++ int idx;
++ int len = 0;
++ int skip_td = 0;
++ union xhci_trb *cur_trb;
++ struct xhci_segment *cur_seg;
++ u32 trb_comp_code;
++
++ ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
++ trb_comp_code = GET_COMP_CODE(event->transfer_len);
++ urb_priv = td->urb->hcpriv;
++ idx = urb_priv->td_cnt;
++
++ if (ep->skip) {
++ /* The transfer is partly done */
++ *status = -EXDEV;
++ td->urb->iso_frame_desc[idx].status = -EXDEV;
++ } else {
++ /* handle completion code */
++ switch (trb_comp_code) {
++ case COMP_SUCCESS:
++ td->urb->iso_frame_desc[idx].status = 0;
++ xhci_dbg(xhci, "Successful isoc transfer!\n");
++ break;
++ case COMP_SHORT_TX:
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ td->urb->iso_frame_desc[idx].status =
++ -EREMOTEIO;
++ else
++ td->urb->iso_frame_desc[idx].status = 0;
++ break;
++ case COMP_BW_OVER:
++ td->urb->iso_frame_desc[idx].status = -ECOMM;
++ skip_td = 1;
++ break;
++ case COMP_BUFF_OVER:
++ case COMP_BABBLE:
++ td->urb->iso_frame_desc[idx].status = -EOVERFLOW;
++ skip_td = 1;
++ break;
++ case COMP_STALL:
++ td->urb->iso_frame_desc[idx].status = -EPROTO;
++ skip_td = 1;
++ break;
++ case COMP_STOP:
++ case COMP_STOP_INVAL:
++ break;
++ default:
++ td->urb->iso_frame_desc[idx].status = -1;
++ break;
++ }
++ }
++
++ /* calc actual length */
++ if (ep->skip) {
++ td->urb->iso_frame_desc[idx].actual_length = 0;
++ return finish_td(xhci, td, event_trb, event, ep, status, true);
++ }
++
++ if (trb_comp_code == COMP_SUCCESS || skip_td == 1) {
++ td->urb->iso_frame_desc[idx].actual_length =
++ td->urb->iso_frame_desc[idx].length;
++ td->urb->actual_length +=
++ td->urb->iso_frame_desc[idx].length;
++ } else {
++ for (cur_trb = ep_ring->dequeue,
++ cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
++ next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
++ if ((cur_trb->generic.field[3] &
++ TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
++ (cur_trb->generic.field[3] &
++ TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
++ len +=
++ TRB_LEN(cur_trb->generic.field[2]);
++ }
++ len += TRB_LEN(cur_trb->generic.field[2]) -
++ TRB_LEN(event->transfer_len);
++
++ if (trb_comp_code != COMP_STOP_INVAL) {
++ td->urb->iso_frame_desc[idx].actual_length = len;
++ td->urb->actual_length += len;
++ }
++ }
++
++ if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS)
++ *status = 0;
++
++ return finish_td(xhci, td, event_trb, event, ep, status, false);
++}
++
++/*
+ * Process bulk and interrupt tds, update urb status and actual_length.
+ */
+ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -1768,6 +1866,9 @@ static int handle_tx_event(struct xhci_h
+ if (usb_endpoint_xfer_control(&td->urb->ep->desc))
+ ret = process_ctrl_td(xhci, td, event_trb, event, ep,
+ &status);
++ else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc))
++ ret = process_isoc_td(xhci, td, event_trb, event, ep,
++ &status);
+ else
+ ret = process_bulk_intr_td(xhci, td, event_trb, event,
+ ep, &status);
+@@ -2553,6 +2654,224 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ return 0;
+ }
+
++static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
++ struct urb *urb, int i)
++{
++ int num_trbs = 0;
++ u64 addr, td_len, running_total;
++
++ addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);
++ td_len = urb->iso_frame_desc[i].length;
++
++ running_total = TRB_MAX_BUFF_SIZE -
++ (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
++ if (running_total != 0)
++ num_trbs++;
++
++ while (running_total < td_len) {
++ num_trbs++;
++ running_total += TRB_MAX_BUFF_SIZE;
++ }
++
++ return num_trbs;
++}
++
++/* This is for isoc transfer */
++static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
++ struct urb *urb, int slot_id, unsigned int ep_index)
++{
++ struct xhci_ring *ep_ring;
++ struct urb_priv *urb_priv;
++ struct xhci_td *td;
++ int num_tds, trbs_per_td;
++ struct xhci_generic_trb *start_trb;
++ bool first_trb;
++ int start_cycle;
++ u32 field, length_field;
++ int running_total, trb_buff_len, td_len, td_remain_len, ret;
++ u64 start_addr, addr;
++ int i, j;
++
++ ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
++
++ num_tds = urb->number_of_packets;
++ if (num_tds < 1) {
++ xhci_dbg(xhci, "Isoc URB with zero packets?\n");
++ return -EINVAL;
++ }
++
++ if (!in_interrupt())
++ dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d),"
++ " addr = %#llx, num_tds = %d\n",
++ urb->ep->desc.bEndpointAddress,
++ urb->transfer_buffer_length,
++ urb->transfer_buffer_length,
++ (unsigned long long)urb->transfer_dma,
++ num_tds);
++
++ start_addr = (u64) urb->transfer_dma;
++ start_trb = &ep_ring->enqueue->generic;
++ start_cycle = ep_ring->cycle_state;
++
++ /* Queue the first TRB, even if it's zero-length */
++ for (i = 0; i < num_tds; i++) {
++ first_trb = true;
++
++ running_total = 0;
++ addr = start_addr + urb->iso_frame_desc[i].offset;
++ td_len = urb->iso_frame_desc[i].length;
++ td_remain_len = td_len;
++
++ trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
++
++ ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
++ urb->stream_id, trbs_per_td, urb, i, mem_flags);
++ if (ret < 0)
++ return ret;
++
++ urb_priv = urb->hcpriv;
++ td = urb_priv->td[i];
++
++ for (j = 0; j < trbs_per_td; j++) {
++ u32 remainder = 0;
++ field = 0;
++
++ if (first_trb) {
++ /* Queue the isoc TRB */
++ field |= TRB_TYPE(TRB_ISOC);
++ /* Assume URB_ISO_ASAP is set */
++ field |= TRB_SIA;
++ if (i > 0)
++ field |= ep_ring->cycle_state;
++ first_trb = false;
++ } else {
++ /* Queue other normal TRBs */
++ field |= TRB_TYPE(TRB_NORMAL);
++ field |= ep_ring->cycle_state;
++ }
++
++ /* Chain all the TRBs together; clear the chain bit in
++ * the last TRB to indicate it's the last TRB in the
++ * chain.
++ */
++ if (j < trbs_per_td - 1) {
++ field |= TRB_CHAIN;
++ } else {
++ td->last_trb = ep_ring->enqueue;
++ field |= TRB_IOC;
++ }
++
++ /* Calculate TRB length */
++ trb_buff_len = TRB_MAX_BUFF_SIZE -
++ (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
++ if (trb_buff_len > td_remain_len)
++ trb_buff_len = td_remain_len;
++
++ remainder = xhci_td_remainder(td_len - running_total);
++ length_field = TRB_LEN(trb_buff_len) |
++ remainder |
++ TRB_INTR_TARGET(0);
++ queue_trb(xhci, ep_ring, false, false,
++ lower_32_bits(addr),
++ upper_32_bits(addr),
++ length_field,
++ /* We always want to know if the TRB was short,
++ * or we won't get an event when it completes.
++ * (Unless we use event data TRBs, which are a
++ * waste of space and HC resources.)
++ */
++ field | TRB_ISP);
++ running_total += trb_buff_len;
++
++ addr += trb_buff_len;
++ td_remain_len -= trb_buff_len;
++ }
++
++ /* Check TD length */
++ if (running_total != td_len) {
++ xhci_err(xhci, "ISOC TD length unmatch\n");
++ return -EINVAL;
++ }
++ }
++
++ wmb();
++ start_trb->field[3] |= start_cycle;
++
++ ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
++ return 0;
++}
++
++/*
++ * Check transfer ring to guarantee there is enough room for the urb.
++ * Update ISO URB start_frame and interval.
++ * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to
++ * update the urb->start_frame by now.
++ * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input.
++ */
++int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
++ struct urb *urb, int slot_id, unsigned int ep_index)
++{
++ struct xhci_virt_device *xdev;
++ struct xhci_ring *ep_ring;
++ struct xhci_ep_ctx *ep_ctx;
++ int start_frame;
++ int xhci_interval;
++ int ep_interval;
++ int num_tds, num_trbs, i;
++ int ret;
++
++ xdev = xhci->devs[slot_id];
++ ep_ring = xdev->eps[ep_index].ring;
++ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++
++ num_trbs = 0;
++ num_tds = urb->number_of_packets;
++ for (i = 0; i < num_tds; i++)
++ num_trbs += count_isoc_trbs_needed(xhci, urb, i);
++
++ /* Check the ring to guarantee there is enough room for the whole urb.
++ * Do not insert any td of the urb to the ring if the check failed.
++ */
++ ret = prepare_ring(xhci, ep_ring, ep_ctx->ep_info & EP_STATE_MASK,
++ num_trbs, mem_flags);
++ if (ret)
++ return ret;
++
++ start_frame = xhci_readl(xhci, &xhci->run_regs->microframe_index);
++ start_frame &= 0x3fff;
++
++ urb->start_frame = start_frame;
++ if (urb->dev->speed == USB_SPEED_LOW ||
++ urb->dev->speed == USB_SPEED_FULL)
++ urb->start_frame >>= 3;
++
++ xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
++ ep_interval = urb->interval;
++ /* Convert to microframes */
++ if (urb->dev->speed == USB_SPEED_LOW ||
++ urb->dev->speed == USB_SPEED_FULL)
++ ep_interval *= 8;
++ /* FIXME change this to a warning and a suggestion to use the new API
++ * to set the polling interval (once the API is added).
++ */
++ if (xhci_interval != ep_interval) {
++ if (!printk_ratelimit())
++ dev_dbg(&urb->dev->dev, "Driver uses different interval"
++ " (%d microframe%s) than xHCI "
++ "(%d microframe%s)\n",
++ ep_interval,
++ ep_interval == 1 ? "" : "s",
++ xhci_interval,
++ xhci_interval == 1 ? "" : "s");
++ urb->interval = xhci_interval;
++ /* Convert back to frames for LS/FS devices */
++ if (urb->dev->speed == USB_SPEED_LOW ||
++ urb->dev->speed == USB_SPEED_FULL)
++ urb->interval /= 8;
++ }
++ return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
++}
++
+ /**** Command Ring Operations ****/
+
+ /* Generic function for queueing a command TRB on the command ring.
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -919,6 +919,9 @@ struct xhci_event_cmd {
+ /* Control transfer TRB specific fields */
+ #define TRB_DIR_IN (1<<16)
+
++/* Isochronous TRB specific fields */
++#define TRB_SIA (1<<31)
++
+ struct xhci_generic_trb {
+ u32 field[4];
+ };
+@@ -1416,6 +1419,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ int slot_id, unsigned int ep_index);
+ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
+ int slot_id, unsigned int ep_index);
++int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
++ struct urb *urb, int slot_id, unsigned int ep_index);
+ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id, bool command_must_succeed);
+ int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
diff --git a/usb/usb-xhci-missed-service-error-event-process.patch b/usb/usb-xhci-missed-service-error-event-process.patch
new file mode 100644
index 00000000000000..47b9dd5c864acb
--- /dev/null
+++ b/usb/usb-xhci-missed-service-error-event-process.patch
@@ -0,0 +1,232 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:16:58 2010
+Date: Thu, 22 Jul 2010 15:23:25 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: Missed Service Error Event process
+Message-ID: <20100722222325.GA21452@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+This patch adds mechanism to process Missed Service Error Event.
+Sometimes the xHC is unable to process the isoc TDs in time, it will
+generate Missed Service Error Event. In this case some TDs on the ring are
+not processed and missed. When encounter a Missed Servce Error Event, set
+the skip flag of the ep, and process the missed TDs until reach the next
+processed TD, then clear the skip flag.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 1
+ drivers/usb/host/xhci-ring.c | 156 +++++++++++++++++++++++++++++--------------
+ drivers/usb/host/xhci.h | 8 ++
+ 3 files changed, 116 insertions(+), 49 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1124,6 +1124,7 @@ int xhci_endpoint_init(struct xhci_hcd *
+ virt_dev->num_rings_cached--;
+ xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring);
+ }
++ virt_dev->eps[ep_index].skip = false;
+ ep_ring = virt_dev->eps[ep_index].new_ring;
+ ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1675,6 +1675,16 @@ static int handle_tx_event(struct xhci_h
+ "still with TDs queued?\n",
+ TRB_TO_SLOT_ID(event->flags), ep_index);
+ goto cleanup;
++ case COMP_MISSED_INT:
++ /*
++ * When encounter missed service error, one or more isoc tds
++ * may be missed by xHC.
++ * Set skip flag of the ep_ring; Complete the missed tds as
++ * short transfer when process the ep_ring next time.
++ */
++ ep->skip = true;
++ xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
++ goto cleanup;
+ default:
+ if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
+ status = 0;
+@@ -1685,60 +1695,108 @@ static int handle_tx_event(struct xhci_h
+ goto cleanup;
+ }
+
+- /* This TRB should be in the TD at the head of this ring's TD list */
+- if (list_empty(&ep_ring->td_list)) {
+- xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+- TRB_TO_SLOT_ID(event->flags), ep_index);
+- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+- (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+- xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+- goto cleanup;
+- }
+- td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
++ do {
++ /* This TRB should be in the TD at the head of this ring's
++ * TD list.
++ */
++ if (list_empty(&ep_ring->td_list)) {
++ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
++ "with no TDs queued?\n",
++ TRB_TO_SLOT_ID(event->flags), ep_index);
++ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
++ (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
++ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
++ if (ep->skip) {
++ ep->skip = false;
++ xhci_dbg(xhci, "td_list is empty while skip "
++ "flag set. Clear skip flag.\n");
++ }
++ ret = 0;
++ goto cleanup;
++ }
+
+- /* Is this a TRB in the currently executing TD? */
+- event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
+- td->last_trb, event_dma);
+- if (!event_seg) {
+- /* HC is busted, give up! */
+- xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
+- return -ESHUTDOWN;
+- }
+- event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
++ td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
++ /* Is this a TRB in the currently executing TD? */
++ event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
++ td->last_trb, event_dma);
++ if (event_seg && ep->skip) {
++ xhci_dbg(xhci, "Found td. Clear skip flag.\n");
++ ep->skip = false;
++ }
++ if (!event_seg &&
++ (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc))) {
++ /* HC is busted, give up! */
++ xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not "
++ "part of current TD\n");
++ return -ESHUTDOWN;
++ }
+
+- /* Now update the urb's actual_length and give back to the core */
+- /* Was this a control transfer? */
+- if (usb_endpoint_xfer_control(&td->urb->ep->desc))
+- ret = process_ctrl_td(xhci, td, event_trb, event, ep,
+- &status);
+- else
+- ret = process_bulk_intr_td(xhci, td, event_trb, event, ep,
+- &status);
++ if (event_seg) {
++ event_trb = &event_seg->trbs[(event_dma -
++ event_seg->dma) / sizeof(*event_trb)];
++ /*
++ * No-op TRB should not trigger interrupts.
++ * If event_trb is a no-op TRB, it means the
++ * corresponding TD has been cancelled. Just ignore
++ * the TD.
++ */
++ if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK)
++ == TRB_TYPE(TRB_TR_NOOP)) {
++ xhci_dbg(xhci, "event_trb is a no-op TRB. "
++ "Skip it\n");
++ goto cleanup;
++ }
++ }
+
+-cleanup:
+- inc_deq(xhci, xhci->event_ring, true);
+- xhci_set_hc_event_deq(xhci);
++ /* Now update the urb's actual_length and give back to
++ * the core
++ */
++ if (usb_endpoint_xfer_control(&td->urb->ep->desc))
++ ret = process_ctrl_td(xhci, td, event_trb, event, ep,
++ &status);
++ else
++ ret = process_bulk_intr_td(xhci, td, event_trb, event,
++ ep, &status);
+
+- /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
+- if (ret) {
+- urb = td->urb;
+- /* Leave the TD around for the reset endpoint function to use
+- * (but only if it's not a control endpoint, since we already
+- * queued the Set TR dequeue pointer command for stalled
+- * control endpoints).
++cleanup:
++ /*
++ * Do not update event ring dequeue pointer if ep->skip is set.
++ * Will roll back to continue process missed tds.
+ */
+- if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+- (trb_comp_code != COMP_STALL &&
+- trb_comp_code != COMP_BABBLE))
+- kfree(td);
+-
+- usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+- xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
+- urb, urb->actual_length, status);
+- spin_unlock(&xhci->lock);
+- usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+- spin_lock(&xhci->lock);
+- }
++ if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
++ inc_deq(xhci, xhci->event_ring, true);
++ xhci_set_hc_event_deq(xhci);
++ }
++
++ if (ret) {
++ urb = td->urb;
++ /* Leave the TD around for the reset endpoint function
++ * to use(but only if it's not a control endpoint,
++ * since we already queued the Set TR dequeue pointer
++ * command for stalled control endpoints).
++ */
++ if (usb_endpoint_xfer_control(&urb->ep->desc) ||
++ (trb_comp_code != COMP_STALL &&
++ trb_comp_code != COMP_BABBLE))
++ kfree(td);
++
++ usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
++ xhci_dbg(xhci, "Giveback URB %p, len = %d, "
++ "status = %d\n",
++ urb, urb->actual_length, status);
++ spin_unlock(&xhci->lock);
++ usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
++ spin_lock(&xhci->lock);
++ }
++
++ /*
++ * If ep->skip is set, it means there are missed tds on the
++ * endpoint ring need to take care of.
++ * Process them as short transfer until reach the td pointed by
++ * the event.
++ */
++ } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
++
+ return 0;
+ }
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -720,6 +720,14 @@ struct xhci_virt_ep {
+ struct timer_list stop_cmd_timer;
+ int stop_cmds_pending;
+ struct xhci_hcd *xhci;
++ /*
++ * Sometimes the xHC can not process isochronous endpoint ring quickly
++ * enough, and it will miss some isoc tds on the ring and generate
++ * a Missed Service Error Event.
++ * Set skip flag when receive a Missed Service Error Event and
++ * process the missed tds on the endpoint ring.
++ */
++ bool skip;
+ };
+
+ struct xhci_virt_device {
diff --git a/usb/usb-xhci-remove-redundant-print-messages.patch b/usb/usb-xhci-remove-redundant-print-messages.patch
new file mode 100644
index 00000000000000..224e660583fc3c
--- /dev/null
+++ b/usb/usb-xhci-remove-redundant-print-messages.patch
@@ -0,0 +1,70 @@
+From sarah.a.sharp@linux.intel.com Thu Jul 22 16:16:27 2010
+Date: Thu, 22 Jul 2010 15:23:15 -0700
+From: Andiry Xu <andiry.xu@amd.com>
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Andiry Xu <andiry.xu@amd.com>
+Subject: USB: xHCI: remove redundant print messages
+Message-ID: <20100722222315.GA21323@xanatos>
+Content-Disposition: inline
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+Remove redundant print messages in the interrupt context.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1592,7 +1592,6 @@ static int handle_tx_event(struct xhci_h
+ u32 trb_comp_code;
+ int ret = 0;
+
+- xhci_dbg(xhci, "In %s\n", __func__);
+ slot_id = TRB_TO_SLOT_ID(event->flags);
+ xdev = xhci->devs[slot_id];
+ if (!xdev) {
+@@ -1614,7 +1613,6 @@ static int handle_tx_event(struct xhci_h
+
+ event_dma = event->buffer;
+ /* This TRB should be in the TD at the head of this ring's TD list */
+- xhci_dbg(xhci, "%s - checking for list empty\n", __func__);
+ if (list_empty(&ep_ring->td_list)) {
+ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+ TRB_TO_SLOT_ID(event->flags), ep_index);
+@@ -1623,30 +1621,17 @@ static int handle_tx_event(struct xhci_h
+ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+ goto cleanup;
+ }
+- xhci_dbg(xhci, "%s - getting list entry\n", __func__);
+ td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
+
+ /* Is this a TRB in the currently executing TD? */
+- xhci_dbg(xhci, "%s - looking for TD\n", __func__);
+ event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
+ td->last_trb, event_dma);
+- xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg);
+ if (!event_seg) {
+ /* HC is busted, give up! */
+ xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
+ return -ESHUTDOWN;
+ }
+ event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
+- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+- (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+- xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
+- lower_32_bits(event->buffer));
+- xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
+- upper_32_bits(event->buffer));
+- xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
+- (unsigned int) event->transfer_len);
+- xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
+- (unsigned int) event->flags);
+
+ /* Look for common error cases */
+ trb_comp_code = GET_COMP_CODE(event->transfer_len);