diff options
Diffstat (limited to 'target/linux/realtek/patches-2.6.30')
9 files changed, 3080 insertions, 1383 deletions
diff --git a/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-nonewfiles.patch b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-nonewfiles.patch index a04cbfc2f..3c0f44cf4 100644 --- a/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-nonewfiles.patch +++ b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-nonewfiles.patch @@ -6156,1339 +6156,3 @@ obj-$(CONFIG_USB_RSPI) += rspiusb/ obj-$(CONFIG_INPUT_MIMIO) += mimio/ obj-$(CONFIG_TRANZPORT) += frontier/ ---- linux-2.6.30.9/drivers/usb/c67x00/c67x00-hcd.h 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/c67x00/c67x00-hcd.h 2013-05-02 01:47:56.720226816 +0300 -@@ -28,7 +28,13 @@ - #include <linux/spinlock.h> - #include <linux/list.h> - #include <linux/usb.h> -+ -+#if defined(CONFIG_USB_UWIFI_HOST) -+#include "../core_uWiFi/hcd.h" -+#else - #include "../core/hcd.h" -+#endif -+ - #include "c67x00.h" - - /* ---- linux-2.6.30.9/drivers/usb/core/devio.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/core/devio.c 2013-05-02 01:47:56.726226815 +0300 -@@ -476,6 +476,9 @@ static int releaseintf(struct dev_state - else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { - usb_driver_release_interface(&usbfs_driver, intf); - err = 0; -+ #if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) -+ mdelay(100); -+ #endif - } - return err; - } ---- linux-2.6.30.9/drivers/usb/core/hcd.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/core/hcd.c 2013-05-02 01:47:56.728226815 +0300 -@@ -82,7 +82,7 @@ - /*-------------------------------------------------------------------------*/ - - /* Keep track of which host controller drivers are loaded */ --unsigned long usb_hcds_loaded; -+unsigned long usb_hcds_loaded=0; - EXPORT_SYMBOL_GPL(usb_hcds_loaded); - - /* host controllers we manage */ -@@ -878,7 +878,7 @@ static void usb_deregister_bus (struct u - * to register the usb device. It also assigns the root hub's USB address - * (always 1). - */ --static int register_root_hub(struct usb_hcd *hcd) -+int register_root_hub(struct usb_hcd *hcd) - { - struct device *parent_dev = hcd->self.controller; - struct usb_device *usb_dev = hcd->self.root_hub; -@@ -923,6 +923,8 @@ static int register_root_hub(struct usb_ - return retval; - } - -+EXPORT_SYMBOL(register_root_hub); -+ - - /*-------------------------------------------------------------------------*/ - ---- linux-2.6.30.9/drivers/usb/core/hub.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/core/hub.c 2013-05-02 01:47:56.731226815 +0300 -@@ -30,6 +30,13 @@ - #include "hcd.h" - #include "hub.h" - -+//#include "rtl865xc_asicregs.h" -+ -+#define REG32(reg) (*(volatile unsigned int *)((unsigned int)reg)) -+#define PABCD_DIR 0xb8003508 -+#define PABCD_DAT 0xb800350C -+#define USB_LED_OFFSET 19 -+ - /* if we are in debug mode, always announce new devices */ - #ifdef DEBUG - #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES -@@ -1432,8 +1439,12 @@ void usb_disconnect(struct usb_device ** - * this quiesces everyting except pending urbs. - */ - usb_set_device_state(udev, USB_STATE_NOTATTACHED); -+ //RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | (1 << EN_USB_LED))); -+ REG32(PABCD_DIR) = REG32(PABCD_DIR) |(0x1<<USB_LED_OFFSET); -+ REG32(PABCD_DAT) = REG32(PABCD_DAT) | (0x1<<USB_LED_OFFSET); - dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); - -+ - usb_lock_device(udev); - - /* Free up all the children before we remove this device */ -@@ -1775,14 +1786,21 @@ static unsigned hub_is_wusb(struct usb_h - return hcd->wireless; - } - -- -+#ifdef CONFIG_RTL_USB_OTG - #define PORT_RESET_TRIES 5 -+#else -+#define PORT_RESET_TRIES 20 -+#endif - #define SET_ADDRESS_TRIES 2 - #define GET_DESCRIPTOR_TRIES 2 - #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) - #define USE_NEW_SCHEME(i) ((i) / 2 == old_scheme_first) - -+#ifdef CONFIG_RTL_USB_OTG - #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ -+#else -+#define HUB_ROOT_RESET_TIME 500 /* times are in msec */ -+#endif - #define HUB_SHORT_RESET_TIME 10 - #define HUB_LONG_RESET_TIME 200 - #define HUB_RESET_TIMEOUT 500 -@@ -1842,8 +1859,13 @@ static int hub_port_wait_reset(struct us - static int hub_port_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, unsigned int delay) - { -+#ifdef CONFIG_RTL_OTGCTRL -+ //slove the usb phy debonce. close the auto-det interrupt -+ extern unsigned int TurnOn_OTGCtrl_Interrupt(unsigned int); //wei add -+ int old=TurnOn_OTGCtrl_Interrupt(0); //wei add -+#endif - int i, status; -- -+ unsigned char retry=3; //realtek patch, if failed, retry 3 times - /* Block EHCI CF initialization during the port reset. - * Some companion controllers don't like it when they mix. - */ -@@ -1868,12 +1890,19 @@ static int hub_port_reset(struct usb_hub - /* return on disconnect or reset */ - switch (status) { - case 0: -+ retry = 0; //realtek patch - /* TRSTRCY = 10 ms; plus some extra */ - msleep(10 + 40); - update_address(udev, 0); - /* FALL THROUGH */ - case -ENOTCONN: - case -ENODEV: -+//realtek patch -+ if(retry){ -+ retry--; -+ continue; -+ } -+//// - clear_port_feature(hub->hdev, - port1, USB_PORT_FEAT_C_RESET); - /* FIXME need disconnect() for NOTATTACHED device */ -@@ -1895,6 +1924,10 @@ static int hub_port_reset(struct usb_hub - - done: - up_read(&ehci_cf_port_reset_rwsem); -+ -+#ifdef CONFIG_RTL_OTGCTRL -+ TurnOn_OTGCtrl_Interrupt(old); //wei add -+#endif - return status; - } - -@@ -2152,15 +2185,31 @@ static int finish_port_resume(struct usb - * - * Returns 0 on success, else negative errno. - */ -+ #define RTL_R32(addr) (*(volatile unsigned long *)(addr)) -+#define RTL_W32(addr, l) ((*(volatile unsigned long*)(addr)) = (l)) -+extern Enable_OTG_Suspend(int sel, int en) ; - int usb_port_resume(struct usb_device *udev, pm_message_t msg) - { - struct usb_hub *hub = hdev_to_hub(udev->parent); - int port1 = udev->portnum; - int status; - u16 portchange, portstatus; -- -+ unsigned int tmp32=0; - /* Skip the initial Clear-Suspend step for a remote wakeup */ - status = hub_port_status(hub, port1, &portstatus, &portchange); -+#if defined(CONFIG_RTL_8196E) && defined(CONFIG_DWC_OTG) -+ //Notify OTG Host to resume -+ msleep(10); -+ Enable_OTG_Suspend(0,0); -+ msleep(10); -+ tmp32 = 0x41100000; -+ RTL_W32(0xB8030440, tmp32); -+ msleep(10); -+ tmp32 = 0x01100000; -+ RTL_W32(0xB8030440, tmp32); -+ msleep(10); -+ ///////////////////////// -+#endif - if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND)) - goto SuspendCleared; - -@@ -2451,6 +2500,13 @@ hub_port_init (struct usb_hub *hub, stru - /* root hub ports have a slightly longer reset period - * (from USB 2.0 spec, section 7.1.7.5) - */ -+ -+ //RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & 0xffffbfff)); -+ -+ REG32(PABCD_DIR) = REG32(PABCD_DIR) |(0x1<<USB_LED_OFFSET); -+ REG32(PABCD_DAT) = REG32(PABCD_DAT) &(~ (0x1<<USB_LED_OFFSET)); -+ -+ - if (!hdev->parent) { - delay = HUB_ROOT_RESET_TIME; - if (port1 == hdev->bus->otg_port) ---- linux-2.6.30.9/drivers/usb/core/urb.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/core/urb.c 2013-05-02 01:47:56.735226815 +0300 -@@ -8,6 +8,12 @@ - #include <linux/wait.h> - #include "hcd.h" - -+#include "bspchip.h" -+ -+#ifndef __IRAM_USB -+#define __IRAM_USB -+#endif -+ - #define to_urb(d) container_of(d, struct urb, kref) - - -@@ -87,6 +93,7 @@ EXPORT_SYMBOL_GPL(usb_alloc_urb); - * Note: The transfer buffer associated with the urb is not freed unless the - * URB_FREE_BUFFER transfer flag is set. - */ -+__IRAM_USB - void usb_free_urb(struct urb *urb) - { - if (urb) -@@ -104,6 +111,7 @@ EXPORT_SYMBOL_GPL(usb_free_urb); - * - * A pointer to the urb with the incremented reference counter is returned. - */ -+__IRAM_USB - struct urb *usb_get_urb(struct urb *urb) - { - if (urb) -@@ -285,6 +293,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); - * GFP_NOIO, unless b) or c) apply - * - */ -+__IRAM_USB - int usb_submit_urb(struct urb *urb, gfp_t mem_flags) - { - int xfertype, max; ---- linux-2.6.30.9/drivers/usb/core/usb.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/core/usb.c 2013-05-02 01:47:56.736226814 +0300 -@@ -43,6 +43,10 @@ - #include "hcd.h" - #include "usb.h" - -+#define REG32(reg) (*(volatile unsigned int *)((unsigned int)reg)) -+#define PIN_MUX_SEL_2 0xb8000044 -+#define PABCD_DIR 0xb8003508 -+#define PABCD_DAT 0xb800350C - - const char *usbcore_name = "usbcore"; - -@@ -1001,6 +1005,16 @@ static struct notifier_block usb_bus_nb - .notifier_call = usb_bus_notify, - }; - -+ -+static void usb_led_init(void) -+{ -+ REG32(PIN_MUX_SEL_2) = REG32(PIN_MUX_SEL_2) |(0x7<<21); -+ REG32(PABCD_DIR) = REG32(PABCD_DIR) |(0x1<<19); -+ REG32(PABCD_DAT) = REG32(PABCD_DAT) |(0x1<<19); -+} -+ -+ -+ - /* - * Init - */ -@@ -1011,7 +1025,7 @@ static int __init usb_init(void) - pr_info("%s: USB support disabled\n", usbcore_name); - return 0; - } -- -+ usb_led_init(); - retval = ksuspend_usb_init(); - if (retval) - goto out; ---- linux-2.6.30.9/drivers/usb/gadget/dummy_hcd.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/gadget/dummy_hcd.c 2013-05-02 01:47:56.782226811 +0300 -@@ -55,7 +55,11 @@ - #include <asm/unaligned.h> - - -+#if defined(CONFIG_USB_UWIFI_HOST) -+#include "../core_uWiFi/hcd.h" -+#else - #include "../core/hcd.h" -+#endif - - - #define DRIVER_DESC "USB Host+Gadget Emulator" ---- linux-2.6.30.9/drivers/usb/host/ehci.h 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ehci.h 2013-05-02 01:47:56.828226807 +0300 -@@ -36,6 +36,11 @@ typedef __u16 __bitwise __hc16; - #define __hc32 __le32 - #define __hc16 __le16 - #endif -+#include "bspchip.h" -+ -+#ifndef __IRAM_USB -+#define __IRAM_USB -+#endif - - /* statistics can be kept for for tuning/monitoring */ - struct ehci_stats { -@@ -602,6 +607,9 @@ ehci_port_speed(struct ehci_hcd *ehci, u - static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) - { -+#if defined(CONFIG_RTL_819X) -+ return (le32_to_cpu((*(volatile unsigned long *)(regs)))); -+#else - #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - return ehci_big_endian_mmio(ehci) ? - readl_be(regs) : -@@ -609,11 +617,15 @@ static inline unsigned int ehci_readl(co - #else - return readl(regs); - #endif -+#endif - } - - static inline void ehci_writel(const struct ehci_hcd *ehci, - const unsigned int val, __u32 __iomem *regs) - { -+#if defined(CONFIG_RTL_819X) -+ ((*(volatile unsigned long *)(regs))=cpu_to_le32(val)); -+#else - #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci_big_endian_mmio(ehci) ? - writel_be(val, regs) : -@@ -621,6 +633,7 @@ static inline void ehci_writel(const str - #else - writel(val, regs); - #endif -+#endif - } - - /* ---- linux-2.6.30.9/drivers/usb/host/ehci-hcd.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ehci-hcd.c 2013-05-02 01:47:56.825226807 +0300 -@@ -169,10 +169,10 @@ static int handshake (struct ehci_hcd *e - u32 result; - - do { -- result = ehci_readl(ehci, ptr); -+ result = (ehci_readl(ehci, ptr))&0xffff; - if (result == ~(u32)0) /* card removed */ - return -ENODEV; -- result &= mask; -+ result &= (mask)&0xffff; - if (result == done) - return 0; - udelay (1); -@@ -429,6 +429,7 @@ static void ehci_port_power (struct ehci - * ehci_work is called from some interrupts, timers, and so on. - * it calls driver completion functions, after dropping ehci->lock. - */ -+__IRAM_USB - static void ehci_work (struct ehci_hcd *ehci) - { - timer_action_done (ehci, TIMER_IO_WATCHDOG); -@@ -677,7 +678,7 @@ static int ehci_run (struct usb_hcd *hcd - } - - /*-------------------------------------------------------------------------*/ -- -+__IRAM_USB - static irqreturn_t ehci_irq (struct usb_hcd *hcd) - { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); -@@ -786,7 +787,19 @@ dead: - } - - if (bh) -+ { -+ #if 1 -+ __asm__ __volatile__( \ -+ ".set push\n\t" \ -+ ".set noreorder\n\t" \ -+ "nop\n\t" \ -+ "nop\n\t" \ -+ "nop\n\t" \ -+ ".set pop\n\t"); -+ #endif -+ - ehci_work (ehci); -+ } - spin_unlock (&ehci->lock); - if (pcd_status) - usb_hcd_poll_rh_status(hcd); -@@ -807,6 +820,7 @@ dead: - * NOTE: control, bulk, and interrupt share the same code to append TDs - * to a (possibly active) QH, and the same QH scanning code. - */ -+__IRAM_USB - static int ehci_urb_enqueue ( - struct usb_hcd *hcd, - struct urb *urb, -@@ -1040,48 +1054,35 @@ MODULE_DESCRIPTION(DRIVER_DESC); - MODULE_AUTHOR (DRIVER_AUTHOR); - MODULE_LICENSE ("GPL"); - --#ifdef CONFIG_PCI -+#ifdef CONFIG_USB_VIA_PCI - #include "ehci-pci.c" - #define PCI_DRIVER ehci_pci_driver - #endif - --#ifdef CONFIG_USB_EHCI_FSL --#include "ehci-fsl.c" --#define PLATFORM_DRIVER ehci_fsl_driver --#endif -- --#ifdef CONFIG_SOC_AU1200 --#include "ehci-au1xxx.c" --#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver --#endif -- --#ifdef CONFIG_PPC_PS3 --#include "ehci-ps3.c" --#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver --#endif -- --#ifdef CONFIG_USB_EHCI_HCD_PPC_OF --#include "ehci-ppc-of.c" --#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver --#endif -- --#ifdef CONFIG_PLAT_ORION --#include "ehci-orion.c" --#define PLATFORM_DRIVER ehci_orion_driver -+#if defined(CONFIG_RTL_819X) -+#include "ehci-rtl8652.c" -+#define PLATFORM_DRIVER ehci_rtl8652_driver - #endif - --#ifdef CONFIG_ARCH_IXP4XX --#include "ehci-ixp4xx.c" --#define PLATFORM_DRIVER ixp4xx_ehci_driver -+#ifdef CONFIG_USB_EHCI_DWC -+#include "ehci-dwc.c" -+#define PLATFORM_DRIVER ehci_dwc_driver - #endif - --#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ -- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) -+#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) - #error "missing bus glue for ehci-hcd" - #endif - -+#if defined(CONFIG_RTL_ULINKER) -+int ehci_hcd_init(void) -+#else - static int __init ehci_hcd_init(void) -+#endif - { -+ if (test_bit(USB_EHCI_LOADED, &usb_hcds_loaded)) -+ { printk("EHCI-HCD: already init \n"); -+ return -1; -+ } - int retval = 0; - - if (usb_disabled()) -@@ -1099,6 +1100,13 @@ static int __init ehci_hcd_init(void) - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - -+#if defined(CONFIG_RTL_819X) -+ if(ehci_rtl8652_init() !=0) -+ { retval = -1; //wei add -+ goto err_out; //wei add -+ } -+#endif -+ - #ifdef DEBUG - ehci_debug_root = debugfs_create_dir("ehci", NULL); - if (!ehci_debug_root) { -@@ -1119,27 +1127,8 @@ static int __init ehci_hcd_init(void) - goto clean1; - #endif - --#ifdef PS3_SYSTEM_BUS_DRIVER -- retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); -- if (retval < 0) -- goto clean2; --#endif -- --#ifdef OF_PLATFORM_DRIVER -- retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); -- if (retval < 0) -- goto clean3; --#endif - return retval; - --#ifdef OF_PLATFORM_DRIVER -- /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ --clean3: --#endif --#ifdef PS3_SYSTEM_BUS_DRIVER -- ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); --clean2: --#endif - #ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); - clean1: -@@ -1153,25 +1142,36 @@ clean0: - ehci_debug_root = NULL; - err_debug: - #endif -+err_out: -+ -+#if defined(CONFIG_RTL_819X) -+ ehci_rtl8652_cleanup(); //wei add -+#endif -+ - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - return retval; - } - module_init(ehci_hcd_init); -- -+//----------------------------------------------------------- -+#if defined(CONFIG_RTL_ULINKER) -+void ehci_hcd_cleanup(void) //wei add -+#else - static void __exit ehci_hcd_cleanup(void) --{ --#ifdef OF_PLATFORM_DRIVER -- of_unregister_platform_driver(&OF_PLATFORM_DRIVER); --#endif --#ifdef PLATFORM_DRIVER -- platform_driver_unregister(&PLATFORM_DRIVER); - #endif -+{ -+ if (!test_bit(USB_EHCI_LOADED, &usb_hcds_loaded)) -+ { printk("EHCI-HCD: not init, cannot cleanup \n"); -+ return; -+ } -+ - #ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); - #endif --#ifdef PS3_SYSTEM_BUS_DRIVER -- ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -+ -+#ifdef PLATFORM_DRIVER -+ platform_driver_unregister(&PLATFORM_DRIVER); - #endif -+ - #ifdef DEBUG - debugfs_remove(ehci_debug_root); - #endif -@@ -1175,6 +1175,10 @@ static void __exit ehci_hcd_cleanup(void - #ifdef DEBUG - debugfs_remove(ehci_debug_root); - #endif -+ -+#if defined(CONFIG_RTL_819X) -+ ehci_rtl8652_cleanup(); //wei add -+#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - } - module_exit(ehci_hcd_cleanup); ---- linux-2.6.30.9/drivers/usb/host/ehci-hub.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ehci-hub.c 2013-05-02 01:47:56.825226807 +0300 -@@ -412,6 +412,16 @@ static int check_reset_complete ( - u32 __iomem *status_reg, - int port_status - ) { -+//realtek patch -+#if 1 /* patch for synopsis USB 2.0 */ -+ int i; -+ #ifdef CONFIG_DWC_OTG -+ static unsigned char retry=1; //if failed, retry 1 times -+ #else -+ static unsigned char retry=3; //if failed, retry 3 times -+ #endif -+#endif -+//// - if (!(port_status & PORT_CONNECT)) - return port_status; - -@@ -425,7 +435,12 @@ static int check_reset_complete ( - index+1); - return port_status; - } -- -+ //realtek patch -+ if(--retry) { -+ return port_status; -+ } -+ retry = 3; -+ ///// - ehci_dbg (ehci, "port %d full speed --> companion\n", - index + 1); - -@@ -438,6 +453,9 @@ static int check_reset_complete ( - if (ehci->has_amcc_usb23) - set_ohci_hcfs(ehci, 1); - } else { -+ //realtek patch -+ retry = 3; //realtek patch -+ //// - ehci_dbg (ehci, "port %d high speed\n", index + 1); - /* ensure 440EPx ohci controller state is suspended */ - if (ehci->has_amcc_usb23) ---- linux-2.6.30.9/drivers/usb/host/ehci-q.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ehci-q.c 2013-05-02 01:47:56.827226807 +0300 -@@ -41,7 +41,7 @@ - /*-------------------------------------------------------------------------*/ - - /* fill a qtd, returning how much of the buffer we were able to queue up */ -- -+__IRAM_USB - static int - qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf, - size_t len, int token, int maxpacket) -@@ -83,7 +83,7 @@ qtd_fill(struct ehci_hcd *ehci, struct e - } - - /*-------------------------------------------------------------------------*/ -- -+__IRAM_USB - static inline void - qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) - { -@@ -118,6 +118,7 @@ qh_update (struct ehci_hcd *ehci, struct - * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault - * recovery (including urb dequeue) would need software changes to a QH... - */ -+__IRAM_USB - static void - qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) - { -@@ -138,7 +139,7 @@ qh_refresh (struct ehci_hcd *ehci, struc - } - - /*-------------------------------------------------------------------------*/ -- -+__IRAM_USB - static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh); - - static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, -@@ -187,7 +188,7 @@ static void ehci_clear_tt_buffer(struct - } - } - } -- -+__IRAM_USB - static int qtd_copy_status ( - struct ehci_hcd *ehci, - struct urb *urb, -@@ -248,7 +249,7 @@ static int qtd_copy_status ( - - return status; - } -- -+__IRAM_USB - static void - ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) - __releases(ehci->lock) -@@ -570,6 +571,7 @@ static void qtd_list_free ( - /* - * create a list of filled qtds for this URB; won't link into qh. - */ -+__IRAM_USB - static struct list_head * - qh_urb_transaction ( - struct ehci_hcd *ehci, -@@ -952,6 +954,7 @@ static void qh_link_async (struct ehci_h - * Returns null if it can't allocate a QH it needs to. - * If the QH has TDs (urbs) already, that's great. - */ -+__IRAM_USB - static struct ehci_qh *qh_append_tds ( - struct ehci_hcd *ehci, - struct urb *urb, -@@ -1033,6 +1036,7 @@ static struct ehci_qh *qh_append_tds ( - - /*-------------------------------------------------------------------------*/ - -+__IRAM_USB - static int - submit_async ( - struct ehci_hcd *ehci, -@@ -1091,6 +1095,7 @@ submit_async ( - - /* the async qh for the qtds being reclaimed are now unlinked from the HC */ - -+__IRAM_USB - static void end_unlink_async (struct ehci_hcd *ehci) - { - struct ehci_qh *qh = ehci->reclaim; -@@ -1132,6 +1137,7 @@ static void end_unlink_async (struct ehc - /* makes sure the async qh will become idle */ - /* caller must own ehci->lock */ - -+__IRAM_USB - static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) - { - int cmd = ehci_readl(ehci, &ehci->regs->command); -@@ -1189,6 +1195,7 @@ static void start_unlink_async (struct e - - /*-------------------------------------------------------------------------*/ - -+__IRAM_USB - static void scan_async (struct ehci_hcd *ehci) - { - struct ehci_qh *qh; ---- linux-2.6.30.9/drivers/usb/host/ehci-sched.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ehci-sched.c 2013-05-02 01:47:56.828226807 +0300 -@@ -33,7 +33,7 @@ - * It keeps track of every ITD (or SITD) that's linked, and holds enough - * pre-calculated schedule data to make appending to the queue be quick. - */ -- -+// #define CONFIG_USB_3G_SUPPORT //for specifical dongle - static int ehci_get_frame (struct usb_hcd *hcd); - - /*-------------------------------------------------------------------------*/ -@@ -323,7 +323,11 @@ static int tt_available ( - * already scheduled transactions - */ - if (125 < usecs) { -+#ifdef CONFIG_USB_3G_SUPPORT -+ nt ufs = (usecs / 125) - 1; -+#else - int ufs = (usecs / 125); -+#endif - int i; - for (i = uframe; i < (uframe + ufs) && i < 8; i++) - if (0 < tt_usecs[i]) { -@@ -436,15 +440,23 @@ static int enable_periodic (struct ehci_ - { - u32 cmd; - int status; -- -+#ifndef CONFIG_USB_3G_SUPPORT - if (ehci->periodic_sched++) - return 0; -+#else -+ udelay(1024); -+#endif - - /* did clearing PSE did take effect yet? - * takes effect only at frame boundaries... - */ - status = handshake_on_error_set_halt(ehci, &ehci->regs->status, -- STS_PSS, 0, 9 * 125); -+ STS_PSS, 0, -+ #ifdef CONFIG_USB_3G_SUPPORT -+ 120000 * 125); -+ #else -+ 9 * 125); -+ #endif - if (status) - return status; - -@@ -471,7 +483,12 @@ static int disable_periodic (struct ehci - * takes effect only at frame boundaries... - */ - status = handshake_on_error_set_halt(ehci, &ehci->regs->status, -- STS_PSS, STS_PSS, 9 * 125); -+ STS_PSS, STS_PSS, -+#ifdef CONFIG_USB_3G_SUPPORT -+ 120000 * 125); -+#else -+ 9 * 125); -+#endif - if (status) - return status; - -@@ -550,7 +567,14 @@ static int qh_link_periodic (struct ehci - : (qh->usecs * 8); - - /* maybe enable periodic schedule processing */ -+#ifdef CONFIG_USB_3G_SUPPORT -+ if (!ehci->periodic_sched++) - return enable_periodic(ehci); -+ return 0; -+ -+#else -+ return enable_periodic(ehci); -+#endif - } - - static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) -@@ -589,7 +613,14 @@ static int qh_unlink_periodic(struct ehc - qh_put (qh); - - /* maybe turn off periodic schedule */ -+ #ifdef CONFIG_USB_3G_SUPPORT -+ ehci->periodic_sched--; -+ if (!ehci->periodic_sched) -+ (void) disable_periodic (ehci); -+ -+ #else - return disable_periodic(ehci); -+ #endif - } - - static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) -@@ -606,9 +637,18 @@ static void intr_deschedule (struct ehci - if (list_empty (&qh->qtd_list) - || (cpu_to_hc32(ehci, QH_CMASK) - & qh->hw_info2) != 0) -+#ifdef CONFIG_USB_3G_SUPPORT -+ wait = 55; -+#else - wait = 2; -+#endif - else -+#ifdef CONFIG_RTL_USB_OTG - wait = 55; /* worst case: 3 * 1024 */ -+#else -+ //wait = 55; /* worst case: 3 * 1024 */ -+ wait = 3 * 1024; -+#endif - - udelay (wait); - qh->qh_state = QH_STATE_IDLE; -@@ -1564,7 +1604,13 @@ itd_link_urb ( - urb->hcpriv = NULL; - - timer_action (ehci, TIMER_IO_WATCHDOG); -+#ifdef CONFIG_USB_3G_SUPPORT -+ if (unlikely (!ehci->periodic_sched++)) -+ return enable_periodic(ehci); -+ return 0; -+#else - return enable_periodic(ehci); -+#endif - } - - #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) -@@ -1645,7 +1691,14 @@ itd_complete ( - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; -+#ifdef CONFIG_USB_3G_SUPPORT -+ /* defer stopping schedule; completion can submit */ -+ ehci->periodic_sched--; -+ if (unlikely (!ehci->periodic_sched)) -+ -+#else - (void) disable_periodic(ehci); -+#endif - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - - if (unlikely(list_is_singular(&stream->td_list))) { -@@ -1967,7 +2020,13 @@ sitd_link_urb ( - urb->hcpriv = NULL; - - timer_action (ehci, TIMER_IO_WATCHDOG); -+#ifdef CONFIG_USB_3G_SUPPORT -+ if (!ehci->periodic_sched++) - return enable_periodic(ehci); -+ return 0; -+#else -+ return enable_periodic(ehci); -+#endif - } - - /*-------------------------------------------------------------------------*/ -@@ -2034,6 +2093,11 @@ sitd_complete ( - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; -+#ifdef CONFIG_USB_3G_SUPPORT -+ /* defer stopping schedule; completion can submit */ -+ ehci->periodic_sched--; -+ if (!ehci->periodic_sched) -+#endif - (void) disable_periodic(ehci); - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - ---- linux-2.6.30.9/drivers/usb/host/Kconfig 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/Kconfig 2013-05-02 01:47:56.823226807 +0300 -@@ -78,6 +78,12 @@ config USB_EHCI_BIG_ENDIAN_DESC - depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) - default y - -+#config USB_EHCI_DWC -+# bool "Support for Synopsys DWC EHCI USB controller" -+# depends on USB_EHCI_HCD -+# select USB_EHCI_ROOT_HUB_TT -+# default y -+ - config USB_EHCI_FSL - bool "Support for Freescale on-chip EHCI USB controller" - depends on USB_EHCI_HCD && FSL_SOC -@@ -88,7 +94,6 @@ config USB_EHCI_FSL - config USB_EHCI_HCD_PPC_OF - bool "EHCI support for PPC USB controller on OF platform bus" - depends on USB_EHCI_HCD && PPC_OF -- default y - ---help--- - Enables support for the USB controller present on the PowerPC - OpenFirmware platform bus. ---- linux-2.6.30.9/drivers/usb/host/Makefile 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/Makefile 2013-05-02 01:47:56.823226807 +0300 -@@ -6,6 +6,9 @@ ifeq ($(CONFIG_USB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG - endif - -+ifeq ($(CONFIG_RTL_819X),y) -+ EXTRA_CFLAGS += -I$(DIR_BOARD) -+endif - isp1760-objs := isp1760-hcd.o isp1760-if.o - fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ - fhci-tds.o fhci-sched.o ---- linux-2.6.30.9/drivers/usb/host/ohci.h 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ohci.h 2013-05-02 01:47:56.839226806 +0300 -@@ -544,6 +544,9 @@ static inline struct usb_hcd *ohci_to_hc - static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, - __hc32 __iomem * regs) - { -+#if defined(CONFIG_RTL_819X) -+ return (le32_to_cpu((*(volatile unsigned long *)(regs)))); -+#else - #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - return big_endian_mmio(ohci) ? - readl_be (regs) : -@@ -551,11 +554,15 @@ static inline unsigned int _ohci_readl ( - #else - return readl (regs); - #endif -+#endif - } - - static inline void _ohci_writel (const struct ohci_hcd *ohci, - const unsigned int val, __hc32 __iomem *regs) - { -+#if defined(CONFIG_RTL_819X) -+ ((*(volatile unsigned long *)(regs))=cpu_to_le32(val)); -+#else - #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - big_endian_mmio(ohci) ? - writel_be (val, regs) : -@@ -563,6 +570,7 @@ static inline void _ohci_writel (const s - #else - writel (val, regs); - #endif -+#endif - } - - #ifdef CONFIG_ARCH_LH7A404 ---- linux-2.6.30.9/drivers/usb/host/ohci-hcd.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/host/ohci-hcd.c 2013-05-02 01:47:56.835226806 +0300 -@@ -1047,6 +1047,11 @@ MODULE_LICENSE ("GPL"); - #define PLATFORM_DRIVER usb_hcd_pnx4008_driver - #endif - -+#if defined(CONFIG_RTL_819X) -+#include "ohci-rtl8652.c" -+#define PLATFORM_DRIVER ohci_hcd_rtl8652_driver -+#endif -+ - #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) || \ -@@ -1092,8 +1097,17 @@ MODULE_LICENSE ("GPL"); - #error "missing bus glue for ohci-hcd" - #endif - -+#if defined(CONFIG_RTL_ULINKER) -+int ohci_hcd_mod_init(void) //wei add -+#else - static int __init ohci_hcd_mod_init(void) -+#endif - { -+ if ( test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) -+ { printk("OHCI-HCD: already init \n"); -+ return -1; -+ } -+ - int retval = 0; - - if (usb_disabled()) -@@ -1104,6 +1118,13 @@ static int __init ohci_hcd_mod_init(void - sizeof (struct ed), sizeof (struct td)); - set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); - -+#if defined(CONFIG_RTL_819X) -+ if(ohci_rtl8652_init() !=0) -+ { retval = -1; //wei add -+ goto err_out; //wei add -+ } -+#endif -+ - #ifdef DEBUG - ohci_debug_root = debugfs_create_dir("ohci", NULL); - if (!ohci_debug_root) { -@@ -1200,14 +1221,26 @@ static int __init ohci_hcd_mod_init(void - ohci_debug_root = NULL; - error_debug: - #endif -- -+err_out: -+#if defined(CONFIG_RTL_819X) -+ ohci_rtl8652_cleanup(); //wei add -+#endif - clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); - return retval; - } - module_init(ohci_hcd_mod_init); -- -+//----------------------------------------------------------- -+#if defined(CONFIG_RTL_ULINKER) -+void ohci_hcd_mod_exit(void) //wei add -+#else - static void __exit ohci_hcd_mod_exit(void) -+#endif - { -+ if (!test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) -+ { printk("OHCI-HCD: not init, cannot cleanup \n"); -+ return; -+ } -+ - #ifdef TMIO_OHCI_DRIVER - platform_driver_unregister(&TMIO_OHCI_DRIVER); - #endif -@@ -1235,6 +1268,10 @@ static void __exit ohci_hcd_mod_exit(voi - #ifdef DEBUG - debugfs_remove(ohci_debug_root); - #endif -+ -+#if defined(CONFIG_RTL_819X) //wei add -+ ohci_rtl8652_cleanup(); -+#endif - clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); - } - module_exit(ohci_hcd_mod_exit); ---- linux-2.6.30.9/drivers/usb/Kconfig 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/Kconfig 2013-05-09 15:45:47.582603984 +0300 -@@ -19,45 +19,18 @@ config USB_ARCH_HAS_HCD - boolean - default y if USB_ARCH_HAS_OHCI - default y if USB_ARCH_HAS_EHCI -- default y if PCMCIA && !M32R # sl811_cs -- default y if ARM # SL-811 -- default y if SUPERH # r8a66597-hcd -- default PCI -+ default y if RTL_819X -+ default y if SOC_HAS_USB - - # many non-PCI SOC chips embed OHCI - config USB_ARCH_HAS_OHCI - boolean -- # ARM: -- default y if SA1111 -- default y if ARCH_OMAP -- default y if ARCH_LH7A404 -- default y if ARCH_S3C2410 -- default y if PXA27x -- default y if PXA3xx -- default y if ARCH_EP93XX -- default y if ARCH_AT91 -- default y if ARCH_PNX4008 && I2C -- default y if MFD_TC6393XB -- # PPC: -- default y if STB03xxx -- default y if PPC_MPC52xx -- # MIPS: -- default y if SOC_AU1X00 -- # SH: -- default y if CPU_SUBTYPE_SH7720 -- default y if CPU_SUBTYPE_SH7721 -- default y if CPU_SUBTYPE_SH7763 -- default y if CPU_SUBTYPE_SH7786 -- # more: -- default PCI -+ default y if RTL_819X - - # some non-PCI hcds implement EHCI - config USB_ARCH_HAS_EHCI - boolean -- default y if PPC_83xx -- default y if SOC_AU1200 -- default y if ARCH_IXP4XX -- default PCI -+ default y if RTL_819X - - # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. - config USB -@@ -149,8 +122,11 @@ source "drivers/usb/misc/Kconfig" - - source "drivers/usb/atm/Kconfig" - --source "drivers/usb/gadget/Kconfig" -+source "drivers/usb/gadget_cathy/Kconfig" -+#source "drivers/usb/gadget/Kconfig" - - source "drivers/usb/otg/Kconfig" - -+source "drivers/usb/dwc_otg/Kconfig" -+ - endif # USB_SUPPORT ---- linux-2.6.30.9/drivers/usb/Makefile 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/Makefile 2013-05-02 01:47:56.716226816 +0300 -@@ -4,10 +4,27 @@ - - # Object files in subdirectories - -+ifeq ($(CONFIG_USB_UWIFI_HOST),y) -+obj-$(CONFIG_USB) += core_uWiFi/ -+else - obj-$(CONFIG_USB) += core/ -+endif - - obj-$(CONFIG_USB_MON) += mon/ - -+ifeq ($(CONFIG_USB_UWIFI_HOST),y) -+obj-$(CONFIG_PCI) += host_uWiFi/ -+obj-$(CONFIG_USB_EHCI_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_ISP116X_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_OHCI_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_UHCI_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_FHCI_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_SL811_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_U132_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_R8A66597_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_HWA_HCD) += host_uWiFi/ -+obj-$(CONFIG_USB_ISP1760_HCD) += host_uWiFi/ -+else - obj-$(CONFIG_PCI) += host/ - obj-$(CONFIG_USB_EHCI_HCD) += host/ - obj-$(CONFIG_USB_ISP116X_HCD) += host/ -@@ -19,6 +36,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/ - obj-$(CONFIG_USB_R8A66597_HCD) += host/ - obj-$(CONFIG_USB_HWA_HCD) += host/ - obj-$(CONFIG_USB_ISP1760_HCD) += host/ -+endif - - obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ - -@@ -29,9 +47,13 @@ obj-$(CONFIG_USB_PRINTER) += class/ - obj-$(CONFIG_USB_WDM) += class/ - obj-$(CONFIG_USB_TMC) += class/ - -+ifeq ($(CONFIG_USB_UWIFI_HOST),y) -+obj-$(CONFIG_USB_STORAGE) += storage_uWiFi/ -+obj-$(CONFIG_USB) += storage_uWiFi/ -+else - obj-$(CONFIG_USB_STORAGE) += storage/ - obj-$(CONFIG_USB) += storage/ -- -+endif - obj-$(CONFIG_USB_MDC800) += image/ - obj-$(CONFIG_USB_MICROTEK) += image/ - -@@ -41,3 +63,12 @@ obj-$(CONFIG_USB) += misc/ - - obj-$(CONFIG_USB_ATM) += atm/ - obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ -+ -+obj-$(CONFIG_DWC_OTG) += dwc_otg/ -+ -+#wei add for otg device mode -+ifeq ($(CONFIG_RTL_USB_OTG),y) -+obj-$(CONFIG_USB_GADGET) += gadget_cathy/ -+else -+obj-$(CONFIG_USB_GADGET) += gadget/ -+endif ---- linux-2.6.30.9/drivers/usb/misc/ftdi-elan.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/misc/ftdi-elan.c 2013-05-02 01:47:56.875226803 +0300 -@@ -73,7 +73,12 @@ static struct list_head ftdi_static_list - */ - #include "usb_u132.h" - #include <asm/io.h> -+ -+#if defined(CONFIG_USB_UWIFI_HOST) -+#include "../core_uWiFi/hcd.h" -+#else - #include "../core/hcd.h" -+#endif - - /* FIXME ohci.h is ONLY for internal use by the OHCI driver. - * If you're going to try stuff like this, you need to split ---- linux-2.6.30.9/drivers/usb/misc/Kconfig 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/misc/Kconfig 2013-05-02 01:47:56.873226803 +0300 -@@ -255,4 +255,4 @@ config USB_VST - To compile this driver as a module, choose M here: the - module will be called vstusb. - -- -+#source "drivers/usb/misc/rts51xx/Kconfig" ---- linux-2.6.30.9/drivers/usb/misc/Makefile 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/misc/Makefile 2013-05-02 01:47:56.873226803 +0300 -@@ -26,6 +26,7 @@ obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o - obj-$(CONFIG_USB_VST) += vstusb.o - - obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ -+#obj-$(CONFIG_RTS5139) += rts51xx/ - - ifeq ($(CONFIG_USB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG ---- linux-2.6.30.9/drivers/usb/mon/mon_main.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/mon/mon_main.c 2013-05-02 01:47:56.892226802 +0300 -@@ -13,7 +13,12 @@ - #include <linux/mutex.h> - - #include "usb_mon.h" -+ -+#if defined(CONFIG_USB_UWIFI_HOST) -+#include "../core_uWiFi/hcd.h" -+#else - #include "../core/hcd.h" -+#endif - - static void mon_stop(struct mon_bus *mbus); - static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); ---- linux-2.6.30.9/drivers/usb/musb/musb_core.h 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/musb/musb_core.h 2013-05-02 01:47:56.895226802 +0300 -@@ -60,7 +60,12 @@ struct musb_ep; - #include "musb_regs.h" - - #include "musb_gadget.h" -+ -+#if defined(CONFIG_USB_UWIFI_HOST) -+#include "../core_uWiFi/hcd.h" -+#else - #include "../core/hcd.h" -+#endif - #include "musb_host.h" - - ---- linux-2.6.30.9/drivers/usb/serial/option.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/serial/option.c 2013-05-02 01:47:56.919226800 +0300 -@@ -161,6 +161,7 @@ static int option_resume(struct usb_ser - #define HUAWEI_PRODUCT_E143D 0x143D - #define HUAWEI_PRODUCT_E143E 0x143E - #define HUAWEI_PRODUCT_E143F 0x143F -+#define HUAWEI_PRODUCT_K4505 0x1464 - - #define QUANTA_VENDOR_ID 0x0408 - #define QUANTA_PRODUCT_Q101 0xEA02 -@@ -297,6 +298,8 @@ static int option_resume(struct usb_ser - #define ZTE_PRODUCT_MF628 0x0015 - #define ZTE_PRODUCT_MF626 0x0031 - #define ZTE_PRODUCT_CDMA_TECH 0xfffe -+#define ZTE_PRODUCT_AC8710 0xfff1 -+#define ZTE_PRODUCT_AC2726 0xfff5 - - #define BENQ_VENDOR_ID 0x04a5 - #define BENQ_PRODUCT_H10 0x4068 -@@ -304,6 +307,19 @@ static int option_resume(struct usb_ser - #define DLINK_VENDOR_ID 0x1186 - #define DLINK_PRODUCT_DWM_652 0x3e04 - -+#define QISDA_VENDOR_ID 0x1da5 -+#define QISDA_PRODUCT_H21_4512 0x4512 -+#define QISDA_PRODUCT_H21_4523 0x4523 -+#define QISDA_PRODUCT_H20_4515 0x4515 -+#define QISDA_PRODUCT_H20_4519 0x4519 -+ -+/* SMPS PRODUCTS */ -+#define SMPS_VENDOR_ID 0xfeed -+#define SMPS_PRODUCT_TITAN20 0x1234 -+ -+/* VIBO */ -+#define VIBO_VENDOR_ID 0x1c9e -+#define VIBO_PRODUCT_D200 0x9605 - - static struct usb_device_id option_ids[] = { - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, -@@ -522,7 +538,25 @@ static struct usb_device_id option_ids[] - { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, - { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, - { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, -- { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ -+ -+ /* bruce: for qisda */ -+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, -+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, -+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, -+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, -+ -+ /* bruce: for ZTE */ -+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, -+ -+ /* mobilepeak */ -+ { USB_DEVICE_AND_INTERFACE_INFO(SMPS_VENDOR_ID, SMPS_PRODUCT_TITAN20, 0xff, 0xff, 0xff) }, -+ -+ /* Huawei*/ -+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, -+ -+ /* vibo */ -+ { USB_DEVICE(VIBO_VENDOR_ID, VIBO_PRODUCT_D200) }, -+ - { } /* Terminating entry */ - }; - MODULE_DEVICE_TABLE(usb, option_ids); -@@ -833,8 +867,9 @@ static void option_instat_callback(struc - dbg("%s: type %x req %x", __func__, - req_pkt->bRequestType, req_pkt->bRequest); - } -- } else -+ } else {/////TODO - err("%s: error %d", __func__, status); -+ } - - /* Resubmit urb so we continue receiving IRQ data */ - if (status != -ESHUTDOWN && status != -ENOENT) { ---- linux-2.6.30.9/drivers/usb/serial/usb-serial.c 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/serial/usb-serial.c 2013-05-02 01:47:56.923226799 +0300 -@@ -35,6 +35,10 @@ - #include <linux/usb/serial.h> - #include "pl2303.h" - -+#if CONFIG_USB_SERIAL_OPTION -+#include <linux/smp_lock.h> /* brucehou, 2010/05/21, for lock_kernel & unlock_kernel */ -+#endif -+ - /* - * Version Information - */ ---- linux-2.6.30.9/drivers/usb/storage/unusual_devs.h 2009-10-05 18:38:08.000000000 +0300 -+++ linux-2.6.30.9-rsdk/drivers/usb/storage/unusual_devs.h 2013-05-02 01:47:56.933226799 +0300 -@@ -1865,6 +1865,13 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0 - "Digital MP3 Audio Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), - -+/* brucehou@RTK for AMOI H01 */ -+UNUSUAL_DEV( 0x1614, 0x0800, 0x0000, 0x0000, -+ "Amoi", -+ "Mass Storage", -+ US_SC_DEVICE, US_PR_DEVICE, option_ms_init, -+ 0), -+ - /* Control/Bulk transport for all SubClass values */ - USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), - USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), diff --git a/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-Kconfig.patch b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-Kconfig.patch new file mode 100644 index 000000000..81f055498 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-Kconfig.patch @@ -0,0 +1,52 @@ +--- linux-2.6.30.9/drivers/usb/Kconfig 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.30.9-rsdk/drivers/usb/Kconfig 2013-05-09 15:45:47.582603984 +0300 +@@ -19,45 +19,18 @@ config USB_ARCH_HAS_HCD + boolean + default y if USB_ARCH_HAS_OHCI + default y if USB_ARCH_HAS_EHCI +- default y if PCMCIA && !M32R # sl811_cs +- default y if ARM # SL-811 +- default y if SUPERH # r8a66597-hcd +- default PCI ++ default y if RTL_819X ++ default y if SOC_HAS_USB + + # many non-PCI SOC chips embed OHCI + config USB_ARCH_HAS_OHCI + boolean +- # ARM: +- default y if SA1111 +- default y if ARCH_OMAP +- default y if ARCH_LH7A404 +- default y if ARCH_S3C2410 +- default y if PXA27x +- default y if PXA3xx +- default y if ARCH_EP93XX +- default y if ARCH_AT91 +- default y if ARCH_PNX4008 && I2C +- default y if MFD_TC6393XB +- # PPC: +- default y if STB03xxx +- default y if PPC_MPC52xx +- # MIPS: +- default y if SOC_AU1X00 +- # SH: +- default y if CPU_SUBTYPE_SH7720 +- default y if CPU_SUBTYPE_SH7721 +- default y if CPU_SUBTYPE_SH7763 +- default y if CPU_SUBTYPE_SH7786 +- # more: +- default PCI ++ default y if RTL_819X + + # some non-PCI hcds implement EHCI + config USB_ARCH_HAS_EHCI + boolean +- default y if PPC_83xx +- default y if SOC_AU1200 +- default y if ARCH_IXP4XX +- default PCI ++ default y if RTL_819X + + # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. + config USB diff --git a/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial-option.patch b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial-option.patch new file mode 100644 index 000000000..c12798187 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial-option.patch @@ -0,0 +1,77 @@ +--- linux-2.6.30.9/drivers/usb/serial/option.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.30.9-rsdk/drivers/usb/serial/option.c 2013-05-02 01:47:56.919226800 +0300 +@@ -161,6 +161,7 @@ static int option_resume(struct usb_ser + #define HUAWEI_PRODUCT_E143D 0x143D + #define HUAWEI_PRODUCT_E143E 0x143E + #define HUAWEI_PRODUCT_E143F 0x143F ++#define HUAWEI_PRODUCT_K4505 0x1464 + + #define QUANTA_VENDOR_ID 0x0408 + #define QUANTA_PRODUCT_Q101 0xEA02 +@@ -297,6 +298,8 @@ static int option_resume(struct usb_ser + #define ZTE_PRODUCT_MF628 0x0015 + #define ZTE_PRODUCT_MF626 0x0031 + #define ZTE_PRODUCT_CDMA_TECH 0xfffe ++#define ZTE_PRODUCT_AC8710 0xfff1 ++#define ZTE_PRODUCT_AC2726 0xfff5 + + #define BENQ_VENDOR_ID 0x04a5 + #define BENQ_PRODUCT_H10 0x4068 +@@ -304,6 +307,19 @@ static int option_resume(struct usb_ser + #define DLINK_VENDOR_ID 0x1186 + #define DLINK_PRODUCT_DWM_652 0x3e04 + ++#define QISDA_VENDOR_ID 0x1da5 ++#define QISDA_PRODUCT_H21_4512 0x4512 ++#define QISDA_PRODUCT_H21_4523 0x4523 ++#define QISDA_PRODUCT_H20_4515 0x4515 ++#define QISDA_PRODUCT_H20_4519 0x4519 ++ ++/* SMPS PRODUCTS */ ++#define SMPS_VENDOR_ID 0xfeed ++#define SMPS_PRODUCT_TITAN20 0x1234 ++ ++/* VIBO */ ++#define VIBO_VENDOR_ID 0x1c9e ++#define VIBO_PRODUCT_D200 0x9605 + + static struct usb_device_id option_ids[] = { + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, +@@ -522,7 +538,25 @@ static struct usb_device_id option_ids[] + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, + { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, +- { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ ++ ++ /* bruce: for qisda */ ++ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, ++ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, ++ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, ++ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, ++ ++ /* bruce: for ZTE */ ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, ++ ++ /* mobilepeak */ ++ { USB_DEVICE_AND_INTERFACE_INFO(SMPS_VENDOR_ID, SMPS_PRODUCT_TITAN20, 0xff, 0xff, 0xff) }, ++ ++ /* Huawei*/ ++ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, ++ ++ /* vibo */ ++ { USB_DEVICE(VIBO_VENDOR_ID, VIBO_PRODUCT_D200) }, ++ + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +@@ -833,8 +867,9 @@ static void option_instat_callback(struc + dbg("%s: type %x req %x", __func__, + req_pkt->bRequestType, req_pkt->bRequest); + } +- } else ++ } else {/////TODO + err("%s: error %d", __func__, status); ++ } + + /* Resubmit urb so we continue receiving IRQ data */ + if (status != -ESHUTDOWN && status != -ENOENT) { diff --git a/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial.patch b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial.patch new file mode 100644 index 000000000..6ab40e6d5 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/0002-rsdk-drivers-usb-serial.patch @@ -0,0 +1,11 @@ +--- linux-2.6.30.9/drivers/usb/serial/usb-serial.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.30.9-rsdk/drivers/usb/serial/usb-serial.c 2013-05-02 01:47:56.923226799 +0300 +@@ -35,6 +35,8 @@ + #include <linux/usb/serial.h> + #include "pl2303.h" + ++#include <linux/smp_lock.h> /* brucehou, 2010/05/21, for lock_kernel & unlock_kernel */ ++ + /* + * Version Information + */ diff --git a/target/linux/realtek/patches-2.6.30/003-include-paths.diff b/target/linux/realtek/patches-2.6.30/003-include-paths.diff index 341cbe8f2..e63b53b12 100644 --- a/target/linux/realtek/patches-2.6.30/003-include-paths.diff +++ b/target/linux/realtek/patches-2.6.30/003-include-paths.diff @@ -1,13 +1,3 @@ -commit 82b68e4028feb70c7c6d6f2c380f342945a6b7f7 -Author: Roman Yeryomin <roman@advem.lv> -Date: Tue Feb 5 01:40:38 2013 +0200 - - adopt 003-include-paths.diff - - Signed-off-by: Roman Yeryomin <roman@advem.lv> - -diff --git a/drivers/net/rtl819x/Makefile b/drivers/net/rtl819x/Makefile -index 7a08142..cfd0152 100644 --- a/drivers/net/rtl819x/Makefile +++ b/drivers/net/rtl819x/Makefile @@ -11,7 +11,7 @@ @@ -19,17 +9,3 @@ index 7a08142..cfd0152 100644 #obj-y := rtl_glue.o #Add mips16 Support -diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index 9e62ed1..19afd87 100644 ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -9,6 +9,9 @@ endif - ifeq ($(CONFIG_RTL_819X),y) - EXTRA_CFLAGS += -I$(DIR_BOARD) - endif -+ -+EXTRA_CFLAGS += -I$(TOPDIR)/arch/rlx -+ - isp1760-objs := isp1760-hcd.o isp1760-if.o - fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ - fhci-tds.o fhci-sched.o diff --git a/target/linux/realtek/patches-2.6.30/114-rlx_819x_usb.patch b/target/linux/realtek/patches-2.6.30/114-rlx_819x_usb.patch new file mode 100644 index 000000000..8bc1f0096 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/114-rlx_819x_usb.patch @@ -0,0 +1,100 @@ +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -1142,6 +1142,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_atmel_driver + #endif + ++#ifdef CONFIG_RTL_819X ++#include "ehci-rtl819x.c" ++#define PLATFORM_DRIVER ehci_rtl819x_driver ++#endif ++ + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) + #error "missing bus glue for ehci-hcd" +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1085,6 +1085,11 @@ MODULE_LICENSE ("GPL"); + #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver + #endif + ++#ifdef CONFIG_RTL_819X ++#include "ohci-rtl819x.c" ++#define PLATFORM_DRIVER ohci_hcd_rtl819x_driver ++#endif ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -611,6 +611,9 @@ ehci_port_speed(struct ehci_hcd *ehci, u + static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, + __u32 __iomem * regs) + { ++#if defined(CONFIG_RTL_819X) ++ return (le32_to_cpu((*(volatile unsigned long *)(regs)))); ++#else + #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + return ehci_big_endian_mmio(ehci) ? + readl_be(regs) : +@@ -618,11 +621,15 @@ static inline unsigned int ehci_readl(co + #else + return readl(regs); + #endif ++#endif + } + + static inline void ehci_writel(const struct ehci_hcd *ehci, + const unsigned int val, __u32 __iomem *regs) + { ++#if defined(CONFIG_RTL_819X) ++ ((*(volatile unsigned long *)(regs))=cpu_to_le32(val)); ++#else + #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + ehci_big_endian_mmio(ehci) ? + writel_be(val, regs) : +@@ -630,6 +637,7 @@ static inline void ehci_writel(const str + #else + writel(val, regs); + #endif ++#endif + } + + /* +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -553,6 +553,9 @@ static inline struct usb_hcd *ohci_to_hc + static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, + __hc32 __iomem * regs) + { ++#if defined(CONFIG_RTL_819X) ++ return (le32_to_cpu((*(volatile unsigned long *)(regs)))); ++#else + #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO + return big_endian_mmio(ohci) ? + readl_be (regs) : +@@ -560,11 +563,15 @@ static inline unsigned int _ohci_readl ( + #else + return readl (regs); + #endif ++#endif + } + + static inline void _ohci_writel (const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) + { ++#if defined(CONFIG_RTL_819X) ++ ((*(volatile unsigned long *)(regs))=cpu_to_le32(val)); ++#else + #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO + big_endian_mmio(ohci) ? + writel_be (val, regs) : +@@ -572,6 +579,7 @@ static inline void _ohci_writel (const s + #else + writel (val, regs); + #endif ++#endif + } + + #ifdef CONFIG_ARCH_LH7A404 diff --git a/target/linux/realtek/patches-2.6.30/2.6.30-to-32-usb.patch b/target/linux/realtek/patches-2.6.30/2.6.30-to-32-usb.patch new file mode 100644 index 000000000..e532924f6 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/2.6.30-to-32-usb.patch @@ -0,0 +1,2840 @@ +diff -ur linux-2.6.30.9/drivers/usb/host/ehci.h linux-2.6.32.27/drivers/usb/host/ehci.h +--- linux-2.6.30.9/drivers/usb/host/ehci.h 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci.h 2010-12-09 23:29:45.000000000 +0200 +@@ -37,7 +37,7 @@ + #define __hc16 __le16 + #endif + +-/* statistics can be kept for for tuning/monitoring */ ++/* statistics can be kept for tuning/monitoring */ + struct ehci_stats { + /* irq usage */ + unsigned long normal; +@@ -87,8 +87,9 @@ + int next_uframe; /* scan periodic, start here */ + unsigned periodic_sched; /* periodic activity count */ + +- /* list of itds completed while clock_frame was still active */ ++ /* list of itds & sitds completed while clock_frame was still active */ + struct list_head cached_itd_list; ++ struct list_head cached_sitd_list; + unsigned clock_frame; + + /* per root hub port */ +@@ -116,7 +117,9 @@ + struct timer_list watchdog; + unsigned long actions; + unsigned stamp; ++ unsigned random_frame; + unsigned long next_statechange; ++ ktime_t last_periodic_enable; + u32 command; + + /* SILICON QUIRKS */ +@@ -125,6 +128,8 @@ + unsigned big_endian_mmio:1; + unsigned big_endian_desc:1; + unsigned has_amcc_usb23:1; ++ unsigned need_io_watchdog:1; ++ unsigned broken_periodic:1; + + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) +@@ -134,6 +139,7 @@ + #define OHCI_HCCTRL_OFFSET 0x4 + #define OHCI_HCCTRL_LEN 0x4 + __hc32 *ohci_hcctrl_reg; ++ unsigned has_hostpc:1; + + u8 sbrn; /* packed release number */ + +@@ -190,7 +196,7 @@ + clear_bit (action, &ehci->actions); + } + +-static void free_cached_itd_list(struct ehci_hcd *ehci); ++static void free_cached_lists(struct ehci_hcd *ehci); + + /*-------------------------------------------------------------------------*/ + +@@ -297,8 +303,8 @@ + * These appear in both the async and (for interrupt) periodic schedules. + */ + +-struct ehci_qh { +- /* first part defined by EHCI spec */ ++/* first part defined by EHCI spec */ ++struct ehci_qh_hw { + __hc32 hw_next; /* see EHCI 3.6.1 */ + __hc32 hw_info1; /* see EHCI 3.6.2 */ + #define QH_HEAD 0x00008000 +@@ -316,7 +322,10 @@ + __hc32 hw_token; + __hc32 hw_buf [5]; + __hc32 hw_buf_hi [5]; ++} __attribute__ ((aligned(32))); + ++struct ehci_qh { ++ struct ehci_qh_hw *hw; + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union ehci_shadow qh_next; /* ptr to qh; or periodic */ +@@ -335,6 +344,7 @@ + u32 refcount; + unsigned stamp; + ++ u8 needs_rescan; /* Dequeue during giveback */ + u8 qh_state; + #define QH_STATE_LINKED 1 /* HC sees this */ + #define QH_STATE_UNLINK 2 /* HC may still see this */ +@@ -356,7 +366,7 @@ + + struct usb_device *dev; /* access to TT */ + unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ +-} __attribute__ ((aligned (32))); ++}; + + /*-------------------------------------------------------------------------*/ + +@@ -385,9 +395,8 @@ + * acts like a qh would, if EHCI had them for ISO. + */ + struct ehci_iso_stream { +- /* first two fields match QH, but info1 == 0 */ +- __hc32 hw_next; +- __hc32 hw_info1; ++ /* first field matches ehci_hq, but is NULL */ ++ struct ehci_qh_hw *hw; + + u32 refcount; + u8 bEndpointAddress; +@@ -543,7 +552,7 @@ + ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) + { + if (ehci_is_TDI(ehci)) { +- switch ((portsc>>26)&3) { ++ switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) { + case 0: + return 0; + case 1: +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-hcd.c linux-2.6.32.27/drivers/usb/host/ehci-hcd.c +--- linux-2.6.30.9/drivers/usb/host/ehci-hcd.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-hcd.c 2010-12-09 23:29:45.000000000 +0200 +@@ -28,9 +28,9 @@ + #include <linux/errno.h> + #include <linux/init.h> + #include <linux/timer.h> ++#include <linux/ktime.h> + #include <linux/list.h> + #include <linux/interrupt.h> +-#include <linux/reboot.h> + #include <linux/usb.h> + #include <linux/moduleparam.h> + #include <linux/dma-mapping.h> +@@ -127,6 +127,8 @@ + + switch (action) { + case TIMER_IO_WATCHDOG: ++ if (!ehci->need_io_watchdog) ++ return; + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: +@@ -239,6 +241,11 @@ + int retval; + u32 command = ehci_readl(ehci, &ehci->regs->command); + ++ /* If the EHCI debug controller is active, special care must be ++ * taken before and after a host controller reset */ ++ if (ehci->debug && !dbgp_reset_prep()) ++ ehci->debug = NULL; ++ + command |= CMD_RESET; + dbg_cmd (ehci, "reset", command); + ehci_writel(ehci, command, &ehci->regs->command); +@@ -247,12 +254,21 @@ + retval = handshake (ehci, &ehci->regs->command, + CMD_RESET, 0, 250 * 1000); + ++ if (ehci->has_hostpc) { ++ ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, ++ (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX)); ++ ehci_writel(ehci, TXFIFO_DEFAULT, ++ (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING)); ++ } + if (retval) + return retval; + + if (ehci_is_TDI(ehci)) + tdi_reset (ehci); + ++ if (ehci->debug) ++ dbgp_external_startup(); ++ + return retval; + } + +@@ -505,9 +521,14 @@ + u32 temp; + int retval; + u32 hcc_params; ++ struct ehci_qh_hw *hw; + + spin_lock_init(&ehci->lock); + ++ /* ++ * keep io watchdog by default, those good HCDs could turn off it later ++ */ ++ ehci->need_io_watchdog = 1; + init_timer(&ehci->watchdog); + ehci->watchdog.function = ehci_watchdog; + ehci->watchdog.data = (unsigned long) ehci; +@@ -522,6 +543,7 @@ + */ + ehci->periodic_size = DEFAULT_I_TDPS; + INIT_LIST_HEAD(&ehci->cached_itd_list); ++ INIT_LIST_HEAD(&ehci->cached_sitd_list); + if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) + return retval; + +@@ -544,12 +566,13 @@ + * from automatically advancing to the next td after short reads. + */ + ehci->async->qh_next.qh = NULL; +- ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); +- ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); +- ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); +- ehci->async->hw_qtd_next = EHCI_LIST_END(ehci); ++ hw = ehci->async->hw; ++ hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); ++ hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); ++ hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); ++ hw->hw_qtd_next = EHCI_LIST_END(ehci); + ehci->async->qh_state = QH_STATE_LINKED; +- ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); ++ hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); + + /* clear interrupt enables, set irq latency */ + if (log2_irq_thresh < 0 || log2_irq_thresh > 6) +@@ -655,6 +678,7 @@ + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + msleep(5); + up_write(&ehci_cf_port_reset_rwsem); ++ ehci->last_periodic_enable = ktime_get_real(); + + temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); + ehci_info (ehci, +@@ -762,9 +786,10 @@ + + /* start 20 msec resume signaling from this port, + * and make khubd collect PORT_STAT_C_SUSPEND to +- * stop that signaling. ++ * stop that signaling. Use 5 ms extra for safety, ++ * like usb_port_resume() does. + */ +- ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ++ ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); + ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + mod_timer(&hcd->rh_timer, ehci->reset_done[i]); + } +@@ -850,12 +875,18 @@ + if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim) + end_unlink_async(ehci); + +- /* if it's not linked then there's nothing to do */ +- if (qh->qh_state != QH_STATE_LINKED) +- ; ++ /* If the QH isn't linked then there's nothing we can do ++ * unless we were called during a giveback, in which case ++ * qh_completions() has to deal with it. ++ */ ++ if (qh->qh_state != QH_STATE_LINKED) { ++ if (qh->qh_state == QH_STATE_COMPLETING) ++ qh->needs_rescan = 1; ++ return; ++ } + + /* defer till later if busy */ +- else if (ehci->reclaim) { ++ if (ehci->reclaim) { + struct ehci_qh *last; + + for (last = ehci->reclaim; +@@ -915,8 +946,9 @@ + break; + switch (qh->qh_state) { + case QH_STATE_LINKED: ++ case QH_STATE_COMPLETING: + intr_deschedule (ehci, qh); +- /* FALL THROUGH */ ++ break; + case QH_STATE_IDLE: + qh_completions (ehci, qh); + break; +@@ -925,23 +957,6 @@ + qh, qh->qh_state); + goto done; + } +- +- /* reschedule QH iff another request is queued */ +- if (!list_empty (&qh->qtd_list) +- && HC_IS_RUNNING (hcd->state)) { +- rc = qh_schedule(ehci, qh); +- +- /* An error here likely indicates handshake failure +- * or no space left in the schedule. Neither fault +- * should happen often ... +- * +- * FIXME kill the now-dysfunctional queued urbs +- */ +- if (rc != 0) +- ehci_err(ehci, +- "can't reschedule qh %p, err %d", +- qh, rc); +- } + break; + + case PIPE_ISOCHRONOUS: +@@ -979,7 +994,7 @@ + /* endpoints can be iso streams. for now, we don't + * accelerate iso completions ... so spin a while. + */ +- if (qh->hw_info1 == 0) { ++ if (qh->hw == NULL) { + ehci_vdbg (ehci, "iso delay\n"); + goto idle_timeout; + } +@@ -988,14 +1003,16 @@ + qh->qh_state = QH_STATE_IDLE; + switch (qh->qh_state) { + case QH_STATE_LINKED: ++ case QH_STATE_COMPLETING: + for (tmp = ehci->async->qh_next.qh; + tmp && tmp != qh; + tmp = tmp->qh_next.qh) + continue; +- /* periodic qh self-unlinks on empty */ +- if (!tmp) +- goto nogood; +- unlink_async (ehci, qh); ++ /* periodic qh self-unlinks on empty, and a COMPLETING qh ++ * may already be unlinked. ++ */ ++ if (tmp) ++ unlink_async(ehci, qh); + /* FALL THROUGH */ + case QH_STATE_UNLINK: /* wait for hw to finish? */ + case QH_STATE_UNLINK_WAIT: +@@ -1012,7 +1029,6 @@ + } + /* else FALL THROUGH */ + default: +-nogood: + /* caller was supposed to have unlinked any requests; + * that's not our job. just leak this memory. + */ +@@ -1027,6 +1043,47 @@ + return; + } + ++static void ++ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ struct ehci_qh *qh; ++ int eptype = usb_endpoint_type(&ep->desc); ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ unsigned long flags; ++ ++ if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) ++ return; ++ ++ spin_lock_irqsave(&ehci->lock, flags); ++ qh = ep->hcpriv; ++ ++ /* For Bulk and Interrupt endpoints we maintain the toggle state ++ * in the hardware; the toggle bits in udev aren't used at all. ++ * When an endpoint is reset by usb_clear_halt() we must reset ++ * the toggle bit in the QH. ++ */ ++ if (qh) { ++ usb_settoggle(qh->dev, epnum, is_out, 0); ++ if (!list_empty(&qh->qtd_list)) { ++ WARN_ONCE(1, "clear_halt for a busy endpoint\n"); ++ } else if (qh->qh_state == QH_STATE_LINKED || ++ qh->qh_state == QH_STATE_COMPLETING) { ++ ++ /* The toggle value in the QH can't be updated ++ * while the QH is active. Unlink it now; ++ * re-linking will call qh_refresh(). ++ */ ++ if (eptype == USB_ENDPOINT_XFER_BULK) ++ unlink_async(ehci, qh); ++ else ++ intr_deschedule(ehci, qh); ++ } ++ } ++ spin_unlock_irqrestore(&ehci->lock, flags); ++} ++ + static int ehci_get_frame (struct usb_hcd *hcd) + { + struct ehci_hcd *ehci = hcd_to_ehci (hcd); +@@ -1075,6 +1132,16 @@ + #define PLATFORM_DRIVER ixp4xx_ehci_driver + #endif + ++#ifdef CONFIG_USB_W90X900_EHCI ++#include "ehci-w90x900.c" ++#define PLATFORM_DRIVER ehci_hcd_w90x900_driver ++#endif ++ ++#ifdef CONFIG_ARCH_AT91 ++#include "ehci-atmel.c" ++#define PLATFORM_DRIVER ehci_atmel_driver ++#endif ++ + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) + #error "missing bus glue for ehci-hcd" +@@ -1100,7 +1167,7 @@ + sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); + + #ifdef DEBUG +- ehci_debug_root = debugfs_create_dir("ehci", NULL); ++ ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); + if (!ehci_debug_root) { + retval = -ENOENT; + goto err_debug; +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-hub.c linux-2.6.32.27/drivers/usb/host/ehci-hub.c +--- linux-2.6.30.9/drivers/usb/host/ehci-hub.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-hub.c 2010-12-09 23:29:45.000000000 +0200 +@@ -111,6 +111,7 @@ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int port; + int mask; ++ u32 __iomem *hostpc_reg = NULL; + + ehci_dbg(ehci, "suspend root hub\n"); + +@@ -119,9 +120,26 @@ + del_timer_sync(&ehci->watchdog); + del_timer_sync(&ehci->iaa_watchdog); + +- port = HCS_N_PORTS (ehci->hcs_params); + spin_lock_irq (&ehci->lock); + ++ /* Once the controller is stopped, port resumes that are already ++ * in progress won't complete. Hence if remote wakeup is enabled ++ * for the root hub and any ports are in the middle of a resume or ++ * remote wakeup, we must fail the suspend. ++ */ ++ if (hcd->self.root_hub->do_remote_wakeup) { ++ port = HCS_N_PORTS(ehci->hcs_params); ++ while (port--) { ++ if (ehci->reset_done[port] != 0) { ++ spin_unlock_irq(&ehci->lock); ++ ehci_dbg(ehci, "suspend failed because " ++ "port %d is resuming\n", ++ port + 1); ++ return -EBUSY; ++ } ++ } ++ } ++ + /* stop schedules, clean any completed work */ + if (HC_IS_RUNNING(hcd->state)) { + ehci_quiesce (ehci); +@@ -137,11 +155,15 @@ + */ + ehci->bus_suspended = 0; + ehci->owned_ports = 0; ++ port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + u32 __iomem *reg = &ehci->regs->port_status [port]; + u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; + u32 t2 = t1; + ++ if (ehci->has_hostpc) ++ hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs ++ + HOSTPC0 + 4 * (port & 0xff)); + /* keep track of which ports we suspend */ + if (t1 & PORT_OWNER) + set_bit(port, &ehci->owned_ports); +@@ -151,15 +173,37 @@ + } + + /* enable remote wakeup on all ports */ +- if (hcd->self.root_hub->do_remote_wakeup) +- t2 |= PORT_WAKE_BITS; +- else ++ if (hcd->self.root_hub->do_remote_wakeup) { ++ /* only enable appropriate wake bits, otherwise the ++ * hardware can not go phy low power mode. If a race ++ * condition happens here(connection change during bits ++ * set), the port change detection will finally fix it. ++ */ ++ if (t1 & PORT_CONNECT) { ++ t2 |= PORT_WKOC_E | PORT_WKDISC_E; ++ t2 &= ~PORT_WKCONN_E; ++ } else { ++ t2 |= PORT_WKOC_E | PORT_WKCONN_E; ++ t2 &= ~PORT_WKDISC_E; ++ } ++ } else + t2 &= ~PORT_WAKE_BITS; + + if (t1 != t2) { + ehci_vdbg (ehci, "port %d, %08x -> %08x\n", + port + 1, t1, t2); + ehci_writel(ehci, t2, reg); ++ if (hostpc_reg) { ++ u32 t3; ++ ++ msleep(5);/* 5ms for HCD enter low pwr mode */ ++ t3 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); ++ t3 = ehci_readl(ehci, hostpc_reg); ++ ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", ++ port, (t3 & HOSTPC_PHCD) ? ++ "succeeded" : "failed"); ++ } + } + } + +@@ -183,6 +227,11 @@ + + ehci->next_statechange = jiffies + msecs_to_jiffies(10); + spin_unlock_irq (&ehci->lock); ++ ++ /* ehci_work() may have re-enabled the watchdog timer, which we do not ++ * want, and so we must delete any pending watchdog timer events. ++ */ ++ del_timer_sync(&ehci->watchdog); + return 0; + } + +@@ -204,6 +253,13 @@ + return -ESHUTDOWN; + } + ++ if (unlikely(ehci->debug)) { ++ if (ehci->debug && !dbgp_reset_prep()) ++ ehci->debug = NULL; ++ else ++ dbgp_external_startup(); ++ } ++ + /* Ideally and we've got a real resume here, and no port's power + * was lost. (For PCI, that means Vaux was maintained.) But we + * could instead be restoring a swsusp snapshot -- so that BIOS was +@@ -236,6 +292,16 @@ + /* manually resume the ports we suspended during bus_suspend() */ + i = HCS_N_PORTS (ehci->hcs_params); + while (i--) { ++ /* clear phy low power mode before resume */ ++ if (ehci->has_hostpc) { ++ u32 __iomem *hostpc_reg = ++ (u32 __iomem *)((u8 *)ehci->regs ++ + HOSTPC0 + 4 * (i & 0xff)); ++ temp = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp & ~HOSTPC_PHCD, ++ hostpc_reg); ++ mdelay(5); ++ } + temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + if (test_bit(i, &ehci->bus_suspended) && +@@ -391,7 +457,7 @@ + + /* with integrated TT there is no companion! */ + if (!ehci_is_TDI(ehci)) +- i = device_create_file(ehci_to_hcd(ehci)->self.dev, ++ i = device_create_file(ehci_to_hcd(ehci)->self.controller, + &dev_attr_companion); + } + +@@ -399,7 +465,7 @@ + { + /* with integrated TT there is no companion! */ + if (!ehci_is_TDI(ehci)) +- device_remove_file(ehci_to_hcd(ehci)->self.dev, ++ device_remove_file(ehci_to_hcd(ehci)->self.controller, + &dev_attr_companion); + } + +@@ -563,7 +629,8 @@ + int ports = HCS_N_PORTS (ehci->hcs_params); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; +- u32 temp, status; ++ u32 __iomem *hostpc_reg = NULL; ++ u32 temp, temp1, status; + unsigned long flags; + int retval = 0; + unsigned selector; +@@ -575,6 +642,9 @@ + * power, "this is the one", etc. EHCI spec supports this. + */ + ++ if (ehci->has_hostpc) ++ hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs ++ + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); + spin_lock_irqsave (&ehci->lock, flags); + switch (typeReq) { + case ClearHubFeature: +@@ -616,6 +686,13 @@ + if (temp & PORT_SUSPEND) { + if ((temp & PORT_PE) == 0) + goto error; ++ /* clear phy low power mode before resume */ ++ if (hostpc_reg) { ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, ++ hostpc_reg); ++ mdelay(5); ++ } + /* resume signaling for 20 msec */ + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + ehci_writel(ehci, temp | PORT_RESUME, +@@ -773,7 +850,11 @@ + if (temp & PORT_CONNECT) { + status |= 1 << USB_PORT_FEAT_CONNECTION; + // status may be from integrated TT +- status |= ehci_port_speed(ehci, temp); ++ if (ehci->has_hostpc) { ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ status |= ehci_port_speed(ehci, temp1); ++ } else ++ status |= ehci_port_speed(ehci, temp); + } + if (temp & PORT_PE) + status |= 1 << USB_PORT_FEAT_ENABLE; +@@ -816,6 +897,15 @@ + case SetPortFeature: + selector = wIndex >> 8; + wIndex &= 0xff; ++ if (unlikely(ehci->debug)) { ++ /* If the debug port is active any port ++ * feature requests should get denied */ ++ if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) && ++ (readl(&ehci->debug->control) & DBGP_ENABLED)) { ++ retval = -ENODEV; ++ goto error_exit; ++ } ++ } + if (!wIndex || wIndex > ports) + goto error; + wIndex--; +@@ -832,6 +922,24 @@ + || (temp & PORT_RESET) != 0) + goto error; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); ++ /* After above check the port must be connected. ++ * Set appropriate bit thus could put phy into low power ++ * mode if we have hostpc feature ++ */ ++ if (hostpc_reg) { ++ temp &= ~PORT_WKCONN_E; ++ temp |= (PORT_WKDISC_E | PORT_WKOC_E); ++ ehci_writel(ehci, temp | PORT_SUSPEND, ++ status_reg); ++ msleep(5);/* 5ms for HCD enter low pwr mode */ ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp1 | HOSTPC_PHCD, ++ hostpc_reg); ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", ++ wIndex, (temp1 & HOSTPC_PHCD) ? ++ "succeeded" : "failed"); ++ } + set_bit(wIndex, &ehci->suspended_ports); + break; + case USB_PORT_FEAT_POWER: +@@ -894,6 +1002,7 @@ + /* "stall" on error */ + retval = -EPIPE; + } ++error_exit: + spin_unlock_irqrestore (&ehci->lock, flags); + return retval; + } +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-mem.c linux-2.6.32.27/drivers/usb/host/ehci-mem.c +--- linux-2.6.30.9/drivers/usb/host/ehci-mem.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-mem.c 2010-12-09 23:29:45.000000000 +0200 +@@ -75,7 +75,8 @@ + } + if (qh->dummy) + ehci_qtd_free (ehci, qh->dummy); +- dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); ++ dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); ++ kfree(qh); + } + + static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) +@@ -83,12 +84,14 @@ + struct ehci_qh *qh; + dma_addr_t dma; + +- qh = (struct ehci_qh *) +- dma_pool_alloc (ehci->qh_pool, flags, &dma); ++ qh = kzalloc(sizeof *qh, GFP_ATOMIC); + if (!qh) +- return qh; +- +- memset (qh, 0, sizeof *qh); ++ goto done; ++ qh->hw = (struct ehci_qh_hw *) ++ dma_pool_alloc(ehci->qh_pool, flags, &dma); ++ if (!qh->hw) ++ goto fail; ++ memset(qh->hw, 0, sizeof *qh->hw); + qh->refcount = 1; + qh->ehci = ehci; + qh->qh_dma = dma; +@@ -99,10 +102,15 @@ + qh->dummy = ehci_qtd_alloc (ehci, flags); + if (qh->dummy == NULL) { + ehci_dbg (ehci, "no dummy td\n"); +- dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); +- qh = NULL; ++ goto fail1; + } ++done: + return qh; ++fail1: ++ dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); ++fail: ++ kfree(qh); ++ return NULL; + } + + /* to share a qh (cpu threads, or hc) */ +@@ -128,7 +136,7 @@ + + static void ehci_mem_cleanup (struct ehci_hcd *ehci) + { +- free_cached_itd_list(ehci); ++ free_cached_lists(ehci); + if (ehci->async) + qh_put (ehci->async); + ehci->async = NULL; +@@ -180,7 +188,7 @@ + /* QHs for control/bulk/intr transfers */ + ehci->qh_pool = dma_pool_create ("ehci_qh", + ehci_to_hcd(ehci)->self.controller, +- sizeof (struct ehci_qh), ++ sizeof(struct ehci_qh_hw), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!ehci->qh_pool) { +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-pci.c linux-2.6.32.27/drivers/usb/host/ehci-pci.c +--- linux-2.6.30.9/drivers/usb/host/ehci-pci.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-pci.c 2010-12-09 23:29:45.000000000 +0200 +@@ -27,28 +27,8 @@ + /* called after powerup, by probe or system-pm "wakeup" */ + static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) + { +- u32 temp; + int retval; + +- /* optional debug port, normally in the first BAR */ +- temp = pci_find_capability(pdev, 0x0a); +- if (temp) { +- pci_read_config_dword(pdev, temp, &temp); +- temp >>= 16; +- if ((temp & (3 << 13)) == (1 << 13)) { +- temp &= 0x1fff; +- ehci->debug = ehci_to_hcd(ehci)->regs + temp; +- temp = ehci_readl(ehci, &ehci->debug->control); +- ehci_info(ehci, "debug port %d%s\n", +- HCS_DEBUG_PORT(ehci->hcs_params), +- (temp & DBGP_ENABLED) +- ? " IN USE" +- : ""); +- if (!(temp & DBGP_ENABLED)) +- ehci->debug = NULL; +- } +- } +- + /* we expect static quirk code to handle the "extended capabilities" + * (currently just BIOS handoff) allowed starting with EHCI 0.96 + */ +@@ -129,6 +109,13 @@ + return retval; + + switch (pdev->vendor) { ++ case PCI_VENDOR_ID_INTEL: ++ ehci->need_io_watchdog = 0; ++ if (pdev->device == 0x27cc) { ++ ehci->broken_periodic = 1; ++ ehci_info(ehci, "using broken periodic workaround\n"); ++ } ++ break; + case PCI_VENDOR_ID_TDI: + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { + hcd->has_tt = 1; +@@ -192,6 +179,25 @@ + break; + } + ++ /* optional debug port, normally in the first BAR */ ++ temp = pci_find_capability(pdev, 0x0a); ++ if (temp) { ++ pci_read_config_dword(pdev, temp, &temp); ++ temp >>= 16; ++ if ((temp & (3 << 13)) == (1 << 13)) { ++ temp &= 0x1fff; ++ ehci->debug = ehci_to_hcd(ehci)->regs + temp; ++ temp = ehci_readl(ehci, &ehci->debug->control); ++ ehci_info(ehci, "debug port %d%s\n", ++ HCS_DEBUG_PORT(ehci->hcs_params), ++ (temp & DBGP_ENABLED) ++ ? " IN USE" ++ : ""); ++ if (!(temp & DBGP_ENABLED)) ++ ehci->debug = NULL; ++ } ++ } ++ + ehci_reset(ehci); + + /* at least the Genesys GL880S needs fixup here */ +@@ -242,7 +248,7 @@ + * System suspend currently expects to be able to suspend the entire + * device tree, device-at-a-time. If we failed selective suspend + * reports, system suspend would fail; so the root hub code must claim +- * success. That's lying to usbcore, and it matters for for runtime ++ * success. That's lying to usbcore, and it matters for runtime + * PM scenarios with selective suspend and remote wakeup... + */ + if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) +@@ -268,7 +274,7 @@ + * Also they depend on separate root hub suspend/resume. + */ + +-static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) ++static int ehci_pci_suspend(struct usb_hcd *hcd) + { + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; +@@ -293,12 +299,6 @@ + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void)ehci_readl(ehci, &ehci->regs->intr_enable); + +- /* make sure snapshot being resumed re-enumerates everything */ +- if (message.event == PM_EVENT_PRETHAW) { +- ehci_halt(ehci); +- ehci_reset(ehci); +- } +- + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ehci->lock, flags); +@@ -309,7 +309,7 @@ + return rc; + } + +-static int ehci_pci_resume(struct usb_hcd *hcd) ++static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) + { + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); +@@ -322,10 +322,12 @@ + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + +- /* If CF is still set, we maintained PCI Vaux power. ++ /* If CF is still set and we aren't resuming from hibernation ++ * then we maintained PCI Vaux power. + * Just undo the effect of ehci_pci_suspend(). + */ +- if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { ++ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && ++ !hibernated) { + int mask = INTR_MASK; + + if (!hcd->self.root_hub->do_remote_wakeup) +@@ -335,7 +337,6 @@ + return 0; + } + +- ehci_dbg(ehci, "lost power, restarting\n"); + usb_root_hub_lost_power(hcd->self.root_hub); + + /* Else reset, to cope with power loss or flush-to-storage +@@ -393,6 +394,7 @@ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, + + /* + * scheduling support +@@ -431,10 +433,11 @@ + + .probe = usb_hcd_pci_probe, + .remove = usb_hcd_pci_remove, ++ .shutdown = usb_hcd_pci_shutdown, + +-#ifdef CONFIG_PM +- .suspend = usb_hcd_pci_suspend, +- .resume = usb_hcd_pci_resume, ++#ifdef CONFIG_PM_SLEEP ++ .driver = { ++ .pm = &usb_hcd_pci_pm_ops ++ }, + #endif +- .shutdown = usb_hcd_pci_shutdown, + }; +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-q.c linux-2.6.32.27/drivers/usb/host/ehci-q.c +--- linux-2.6.30.9/drivers/usb/host/ehci-q.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-q.c 2010-12-09 23:29:45.000000000 +0200 +@@ -87,31 +87,33 @@ + static inline void + qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) + { ++ struct ehci_qh_hw *hw = qh->hw; ++ + /* writes to an active overlay are unsafe */ + BUG_ON(qh->qh_state != QH_STATE_IDLE); + +- qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); +- qh->hw_alt_next = EHCI_LIST_END(ehci); ++ hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); ++ hw->hw_alt_next = EHCI_LIST_END(ehci); + + /* Except for control endpoints, we make hardware maintain data + * toggle (like OHCI) ... here (re)initialize the toggle in the QH, + * and set the pseudo-toggle in udev. Only usb_clear_halt() will + * ever clear it. + */ +- if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { ++ if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { + unsigned is_out, epnum; + + is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); +- epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; ++ epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; + if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { +- qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); ++ hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); + usb_settoggle (qh->dev, epnum, is_out, 1); + } + } + + /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ + wmb (); +- qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); ++ hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); + } + + /* if it weren't for a common silicon quirk (writing the dummy into the qh +@@ -129,7 +131,7 @@ + qtd = list_entry (qh->qtd_list.next, + struct ehci_qtd, qtd_list); + /* first qtd may already be partially processed */ +- if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current) ++ if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) + qtd = NULL; + } + +@@ -214,6 +216,14 @@ + if (token & QTD_STS_BABBLE) { + /* FIXME "must" disable babbling device's port too */ + status = -EOVERFLOW; ++ /* CERR nonzero + halt --> stall */ ++ } else if (QTD_CERR(token)) { ++ status = -EPIPE; ++ ++ /* In theory, more than one of the following bits can be set ++ * since they are sticky and the transaction is retried. ++ * Which to test first is rather arbitrary. ++ */ + } else if (token & QTD_STS_MMF) { + /* fs/ls interrupt xfer missed the complete-split */ + status = -EPROTO; +@@ -222,21 +232,15 @@ + ? -ENOSR /* hc couldn't read data */ + : -ECOMM; /* hc couldn't write data */ + } else if (token & QTD_STS_XACT) { +- /* timeout, bad crc, wrong PID, etc; retried */ +- if (QTD_CERR (token)) +- status = -EPIPE; +- else { +- ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", +- urb->dev->devpath, +- usb_pipeendpoint (urb->pipe), +- usb_pipein (urb->pipe) ? "in" : "out"); +- status = -EPROTO; +- } +- /* CERR nonzero + no errors + halt --> stall */ +- } else if (QTD_CERR (token)) +- status = -EPIPE; +- else /* unknown */ ++ /* timeout, bad CRC, wrong PID, etc */ ++ ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n", ++ urb->dev->devpath, ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "in" : "out"); + status = -EPROTO; ++ } else { /* unknown */ ++ status = -EPROTO; ++ } + + ehci_vdbg (ehci, + "dev%d ep%d%s qtd token %08x --> status %d\n", +@@ -258,7 +262,7 @@ + struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; + + /* S-mask in a QH means it's an interrupt urb */ +- if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { ++ if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { + + /* ... update hc-wide periodic stats (for usbfs) */ + ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; +@@ -295,7 +299,6 @@ + static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); + static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); + +-static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh); + static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); + + /* +@@ -306,13 +309,14 @@ + static unsigned + qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) + { +- struct ehci_qtd *last = NULL, *end = qh->dummy; ++ struct ehci_qtd *last, *end = qh->dummy; + struct list_head *entry, *tmp; +- int last_status = -EINPROGRESS; ++ int last_status; + int stopped; + unsigned count = 0; + u8 state; +- __le32 halt = HALT_BIT(ehci); ++ const __le32 halt = HALT_BIT(ehci); ++ struct ehci_qh_hw *hw = qh->hw; + + if (unlikely (list_empty (&qh->qtd_list))) + return count; +@@ -322,11 +326,20 @@ + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. ++ * ++ * It's a bug for qh->qh_state to be anything other than ++ * QH_STATE_IDLE, unless our caller is scan_async() or ++ * scan_periodic(). + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + ++ rescan: ++ last = NULL; ++ last_status = -EINPROGRESS; ++ qh->needs_rescan = 0; ++ + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. +@@ -373,12 +386,11 @@ + */ + if ((token & QTD_STS_XACT) && + QTD_CERR(token) == 0 && +- --qh->xacterrs > 0 && ++ ++qh->xacterrs < QH_XACTERR_MAX && + !urb->unlinked) { + ehci_dbg(ehci, + "detected XactErr len %zu/%zu retry %d\n", +- qtd->length - QTD_LENGTH(token), qtd->length, +- QH_XACTERR_MAX - qh->xacterrs); ++ qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains +@@ -391,7 +403,8 @@ + qtd->hw_token = cpu_to_hc32(ehci, + token); + wmb(); +- qh->hw_token = cpu_to_hc32(ehci, token); ++ hw->hw_token = cpu_to_hc32(ehci, ++ token); + goto retry_xacterr; + } + stopped = 1; +@@ -434,8 +447,8 @@ + /* qh unlinked; token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(ehci, qtd->qtd_dma) +- == qh->hw_current) { +- token = hc32_to_cpu(ehci, qh->hw_token); ++ == hw->hw_current) { ++ token = hc32_to_cpu(ehci, hw->hw_token); + + /* An unlink may leave an incomplete + * async transaction in the TT buffer. +@@ -448,9 +461,9 @@ + * patch the qh later and so that completions can't + * activate it while we "know" it's stopped. + */ +- if ((halt & qh->hw_token) == 0) { ++ if ((halt & hw->hw_token) == 0) { + halt: +- qh->hw_token |= halt; ++ hw->hw_token |= halt; + wmb (); + } + } +@@ -474,8 +487,20 @@ + * we must clear the TT buffer (11.17.5). + */ + if (unlikely(last_status != -EINPROGRESS && +- last_status != -EREMOTEIO)) +- ehci_clear_tt_buffer(ehci, qh, urb, token); ++ last_status != -EREMOTEIO)) { ++ /* The TT's in some hubs malfunction when they ++ * receive this request following a STALL (they ++ * stop sending isochronous packets). Since a ++ * STALL can't leave the TT buffer in a busy ++ * state (if you believe Figures 11-48 - 11-51 ++ * in the USB 2.0 spec), we won't clear the TT ++ * buffer in this case. Strictly speaking this ++ * is a violation of the spec. ++ */ ++ if (last_status != -EPIPE) ++ ehci_clear_tt_buffer(ehci, qh, urb, ++ token); ++ } + } + + /* if we're removing something not at the queue head, +@@ -492,7 +517,7 @@ + last = qtd; + + /* reinit the xacterr counter for the next qtd */ +- qh->xacterrs = QH_XACTERR_MAX; ++ qh->xacterrs = 0; + } + + /* last urb's completion might still need calling */ +@@ -502,6 +527,21 @@ + ehci_qtd_free (ehci, last); + } + ++ /* Do we need to rescan for URBs dequeued during a giveback? */ ++ if (unlikely(qh->needs_rescan)) { ++ /* If the QH is already unlinked, do the rescan now. */ ++ if (state == QH_STATE_IDLE) ++ goto rescan; ++ ++ /* Otherwise we have to wait until the QH is fully unlinked. ++ * Our caller will start an unlink if qh->needs_rescan is ++ * set. But if an unlink has already started, nothing needs ++ * to be done. ++ */ ++ if (state != QH_STATE_LINKED) ++ qh->needs_rescan = 0; ++ } ++ + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + +@@ -509,7 +549,7 @@ + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ +- if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { ++ if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); +@@ -526,12 +566,9 @@ + * That should be rare for interrupt transfers, + * except maybe high bandwidth ... + */ +- if ((cpu_to_hc32(ehci, QH_SMASK) +- & qh->hw_info2) != 0) { +- intr_deschedule (ehci, qh); +- (void) qh_schedule (ehci, qh); +- } else +- unlink_async (ehci, qh); ++ ++ /* Tell the caller to start an unlink */ ++ qh->needs_rescan = 1; + break; + /* otherwise, unlink already started */ + } +@@ -648,7 +685,7 @@ + * (this will usually be overridden later.) + */ + if (is_input) +- qtd->hw_alt_next = ehci->async->hw_alt_next; ++ qtd->hw_alt_next = ehci->async->hw->hw_alt_next; + + /* qh makes control packets use qtd toggle; maybe switch it */ + if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) +@@ -743,6 +780,7 @@ + int is_input, type; + int maxp = 0; + struct usb_tt *tt = urb->dev->tt; ++ struct ehci_qh_hw *hw; + + if (!qh) + return qh; +@@ -789,9 +827,10 @@ + * But interval 1 scheduling is simpler, and + * includes high bandwidth. + */ +- dbg ("intr period %d uframes, NYET!", +- urb->interval); +- goto done; ++ urb->interval = 1; ++ } else if (qh->period > ehci->periodic_size) { ++ qh->period = ehci->periodic_size; ++ urb->interval = qh->period << 3; + } + } else { + int think_time; +@@ -814,6 +853,10 @@ + usb_calc_bus_time (urb->dev->speed, + is_input, 0, max_packet (maxp))); + qh->period = urb->interval; ++ if (qh->period > ehci->periodic_size) { ++ qh->period = ehci->periodic_size; ++ urb->interval = qh->period; ++ } + } + } + +@@ -889,8 +932,9 @@ + + /* init as live, toggle clear, advance to dummy */ + qh->qh_state = QH_STATE_IDLE; +- qh->hw_info1 = cpu_to_hc32(ehci, info1); +- qh->hw_info2 = cpu_to_hc32(ehci, info2); ++ hw = qh->hw; ++ hw->hw_info1 = cpu_to_hc32(ehci, info1); ++ hw->hw_info2 = cpu_to_hc32(ehci, info2); + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); + qh_refresh (ehci, qh); + return qh; +@@ -909,6 +953,8 @@ + if (unlikely(qh->clearing_tt)) + return; + ++ WARN_ON(qh->qh_state != QH_STATE_IDLE); ++ + /* (re)start the async schedule? */ + head = ehci->async; + timer_action_done (ehci, TIMER_ASYNC_OFF); +@@ -927,19 +973,18 @@ + } + + /* clear halt and/or toggle; and maybe recover from silicon quirk */ +- if (qh->qh_state == QH_STATE_IDLE) +- qh_refresh (ehci, qh); ++ qh_refresh(ehci, qh); + + /* splice right after start */ + qh->qh_next = head->qh_next; +- qh->hw_next = head->hw_next; ++ qh->hw->hw_next = head->hw->hw_next; + wmb (); + + head->qh_next.qh = qh; +- head->hw_next = dma; ++ head->hw->hw_next = dma; + + qh_get(qh); +- qh->xacterrs = QH_XACTERR_MAX; ++ qh->xacterrs = 0; + qh->qh_state = QH_STATE_LINKED; + /* qtd completions reported later by interrupt */ + } +@@ -983,7 +1028,7 @@ + + /* usb_reset_device() briefly reverts to address 0 */ + if (usb_pipedevice (urb->pipe) == 0) +- qh->hw_info1 &= ~qh_addr_mask; ++ qh->hw->hw_info1 &= ~qh_addr_mask; + } + + /* just one way to queue requests: swap with the dummy qtd. +@@ -1168,7 +1213,7 @@ + while (prev->qh_next.qh != qh) + prev = prev->qh_next.qh; + +- prev->hw_next = qh->hw_next; ++ prev->hw->hw_next = qh->hw->hw_next; + prev->qh_next = qh->qh_next; + wmb (); + +@@ -1213,6 +1258,8 @@ + qh = qh_get (qh); + qh->stamp = ehci->stamp; + temp = qh_completions (ehci, qh); ++ if (qh->needs_rescan) ++ unlink_async(ehci, qh); + qh_put (qh); + if (temp != 0) { + goto rescan; +diff -ur linux-2.6.30.9/drivers/usb/host/ehci-sched.c linux-2.6.32.27/drivers/usb/host/ehci-sched.c +--- linux-2.6.30.9/drivers/usb/host/ehci-sched.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ehci-sched.c 2010-12-09 23:29:45.000000000 +0200 +@@ -60,6 +60,20 @@ + } + } + ++static __hc32 * ++shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, ++ __hc32 tag) ++{ ++ switch (hc32_to_cpu(ehci, tag)) { ++ /* our ehci_shadow.qh is actually software part */ ++ case Q_TYPE_QH: ++ return &periodic->qh->hw->hw_next; ++ /* others are hw parts */ ++ default: ++ return periodic->hw_next; ++ } ++} ++ + /* caller must hold ehci->lock */ + static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) + { +@@ -71,7 +85,8 @@ + while (here.ptr && here.ptr != ptr) { + prev_p = periodic_next_shadow(ehci, prev_p, + Q_NEXT_TYPE(ehci, *hw_p)); +- hw_p = here.hw_next; ++ hw_p = shadow_next_periodic(ehci, &here, ++ Q_NEXT_TYPE(ehci, *hw_p)); + here = *prev_p; + } + /* an interrupt entry (at list end) could have been shared */ +@@ -83,7 +98,7 @@ + */ + *prev_p = *periodic_next_shadow(ehci, &here, + Q_NEXT_TYPE(ehci, *hw_p)); +- *hw_p = *here.hw_next; ++ *hw_p = *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)); + } + + /* how many of the uframe's 125 usecs are allocated? */ +@@ -93,18 +108,20 @@ + __hc32 *hw_p = &ehci->periodic [frame]; + union ehci_shadow *q = &ehci->pshadow [frame]; + unsigned usecs = 0; ++ struct ehci_qh_hw *hw; + + while (q->ptr) { + switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { + case Q_TYPE_QH: ++ hw = q->qh->hw; + /* is it in the S-mask? */ +- if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) ++ if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) + usecs += q->qh->usecs; + /* ... or C-mask? */ +- if (q->qh->hw_info2 & cpu_to_hc32(ehci, ++ if (hw->hw_info2 & cpu_to_hc32(ehci, + 1 << (8 + uframe))) + usecs += q->qh->c_usecs; +- hw_p = &q->qh->hw_next; ++ hw_p = &hw->hw_next; + q = &q->qh->qh_next; + break; + // case Q_TYPE_FSTN: +@@ -237,10 +254,10 @@ + continue; + case Q_TYPE_QH: + if (same_tt(dev, q->qh->dev)) { +- uf = tt_start_uframe(ehci, q->qh->hw_info2); ++ uf = tt_start_uframe(ehci, q->qh->hw->hw_info2); + tt_usecs[uf] += q->qh->tt_usecs; + } +- hw_p = &q->qh->hw_next; ++ hw_p = &q->qh->hw->hw_next; + q = &q->qh->qh_next; + continue; + case Q_TYPE_SITD: +@@ -375,6 +392,7 @@ + for (; frame < ehci->periodic_size; frame += period) { + union ehci_shadow here; + __hc32 type; ++ struct ehci_qh_hw *hw; + + here = ehci->pshadow [frame]; + type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); +@@ -385,17 +403,18 @@ + here = here.itd->itd_next; + continue; + case Q_TYPE_QH: ++ hw = here.qh->hw; + if (same_tt (dev, here.qh->dev)) { + u32 mask; + + mask = hc32_to_cpu(ehci, +- here.qh->hw_info2); ++ hw->hw_info2); + /* "knows" no gap is needed */ + mask |= mask >> 8; + if (mask & uf_mask) + break; + } +- type = Q_NEXT_TYPE(ehci, here.qh->hw_next); ++ type = Q_NEXT_TYPE(ehci, hw->hw_next); + here = here.qh->qh_next; + continue; + case Q_TYPE_SITD: +@@ -456,6 +475,8 @@ + /* make sure ehci_work scans these */ + ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) + % (ehci->periodic_size << 3); ++ if (unlikely(ehci->broken_periodic)) ++ ehci->last_periodic_enable = ktime_get_real(); + return 0; + } + +@@ -467,6 +488,16 @@ + if (--ehci->periodic_sched) + return 0; + ++ if (unlikely(ehci->broken_periodic)) { ++ /* delay experimentally determined */ ++ ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000); ++ ktime_t now = ktime_get_real(); ++ s64 delay = ktime_us_delta(safe, now); ++ ++ if (unlikely(delay > 0)) ++ udelay(delay); ++ } ++ + /* did setting PSE not take effect yet? + * takes effect only at frame boundaries... + */ +@@ -498,7 +529,8 @@ + + dev_dbg (&qh->dev->dev, + "link qh%d-%04x/%p start %d [%d/%d us]\n", +- period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), ++ period, hc32_to_cpup(ehci, &qh->hw->hw_info2) ++ & (QH_CMASK | QH_SMASK), + qh, qh->start, qh->usecs, qh->c_usecs); + + /* high bandwidth, or otherwise every microframe */ +@@ -517,7 +549,7 @@ + if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) + break; + prev = periodic_next_shadow(ehci, prev, type); +- hw_p = &here.qh->hw_next; ++ hw_p = shadow_next_periodic(ehci, &here, type); + here = *prev; + } + +@@ -528,20 +560,21 @@ + if (qh->period > here.qh->period) + break; + prev = &here.qh->qh_next; +- hw_p = &here.qh->hw_next; ++ hw_p = &here.qh->hw->hw_next; + here = *prev; + } + /* link in this qh, unless some earlier pass did that */ + if (qh != here.qh) { + qh->qh_next = here; + if (here.qh) +- qh->hw_next = *hw_p; ++ qh->hw->hw_next = *hw_p; + wmb (); + prev->qh = qh; + *hw_p = QH_NEXT (ehci, qh->qh_dma); + } + } + qh->qh_state = QH_STATE_LINKED; ++ qh->xacterrs = 0; + qh_get (qh); + + /* update per-qh bandwidth for usbfs */ +@@ -580,7 +613,7 @@ + dev_dbg (&qh->dev->dev, + "unlink qh%d-%04x/%p start %d [%d/%d us]\n", + qh->period, +- hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), ++ hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), + qh, qh->start, qh->usecs, qh->c_usecs); + + /* qh->qh_next still "live" to HC */ +@@ -594,7 +627,19 @@ + + static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) + { +- unsigned wait; ++ unsigned wait; ++ struct ehci_qh_hw *hw = qh->hw; ++ int rc; ++ ++ /* If the QH isn't linked then there's nothing we can do ++ * unless we were called during a giveback, in which case ++ * qh_completions() has to deal with it. ++ */ ++ if (qh->qh_state != QH_STATE_LINKED) { ++ if (qh->qh_state == QH_STATE_COMPLETING) ++ qh->needs_rescan = 1; ++ return; ++ } + + qh_unlink_periodic (ehci, qh); + +@@ -605,15 +650,33 @@ + */ + if (list_empty (&qh->qtd_list) + || (cpu_to_hc32(ehci, QH_CMASK) +- & qh->hw_info2) != 0) ++ & hw->hw_info2) != 0) + wait = 2; + else + wait = 55; /* worst case: 3 * 1024 */ + + udelay (wait); + qh->qh_state = QH_STATE_IDLE; +- qh->hw_next = EHCI_LIST_END(ehci); ++ hw->hw_next = EHCI_LIST_END(ehci); + wmb (); ++ ++ qh_completions(ehci, qh); ++ ++ /* reschedule QH iff another request is queued */ ++ if (!list_empty(&qh->qtd_list) && ++ HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { ++ rc = qh_schedule(ehci, qh); ++ ++ /* An error here likely indicates handshake failure ++ * or no space left in the schedule. Neither fault ++ * should happen often ... ++ * ++ * FIXME kill the now-dysfunctional queued urbs ++ */ ++ if (rc != 0) ++ ehci_err(ehci, "can't reschedule qh %p, err %d\n", ++ qh, rc); ++ } + } + + /*-------------------------------------------------------------------------*/ +@@ -738,14 +801,15 @@ + unsigned uframe; + __hc32 c_mask; + unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ ++ struct ehci_qh_hw *hw = qh->hw; + + qh_refresh(ehci, qh); +- qh->hw_next = EHCI_LIST_END(ehci); ++ hw->hw_next = EHCI_LIST_END(ehci); + frame = qh->start; + + /* reuse the previous schedule slots, if we can */ + if (frame < qh->period) { +- uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK); ++ uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK); + status = check_intr_schedule (ehci, frame, --uframe, + qh, &c_mask); + } else { +@@ -760,8 +824,10 @@ + if (status) { + /* "normal" case, uframing flexible except with splits */ + if (qh->period) { +- frame = qh->period - 1; +- do { ++ int i; ++ ++ for (i = qh->period; status && i > 0; --i) { ++ frame = ++ehci->random_frame % qh->period; + for (uframe = 0; uframe < 8; uframe++) { + status = check_intr_schedule (ehci, + frame, uframe, qh, +@@ -769,7 +835,7 @@ + if (status == 0) + break; + } +- } while (status && frame--); ++ } + + /* qh->period == 0 means every uframe */ + } else { +@@ -781,11 +847,11 @@ + qh->start = frame; + + /* reset S-frame and (maybe) C-frame masks */ +- qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); +- qh->hw_info2 |= qh->period ++ hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); ++ hw->hw_info2 |= qh->period + ? cpu_to_hc32(ehci, 1 << uframe) + : cpu_to_hc32(ehci, QH_SMASK); +- qh->hw_info2 |= c_mask; ++ hw->hw_info2 |= c_mask; + } else + ehci_dbg (ehci, "reused qh %p schedule\n", qh); + +@@ -1055,8 +1121,8 @@ + urb->interval); + } + +- /* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */ +- } else if (unlikely (stream->hw_info1 != 0)) { ++ /* if dev->ep [epnum] is a QH, hw is set */ ++ } else if (unlikely (stream->hw != NULL)) { + ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", + urb->dev->devpath, epnum, + usb_pipein(urb->pipe) ? "in" : "out"); +@@ -1346,6 +1412,10 @@ + goto fail; + } + ++ period = urb->interval; ++ if (!stream->highspeed) ++ period <<= 3; ++ + now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; + + /* when's the last uframe this urb could start? */ +@@ -1363,14 +1433,15 @@ + + /* Fell behind (by up to twice the slop amount)? */ + if (start >= max - 2 * 8 * SCHEDULE_SLOP) +- start += stream->interval * DIV_ROUND_UP( +- max - start, stream->interval) - mod; ++ start += period * DIV_ROUND_UP( ++ max - start, period) - mod; + + /* Tried to schedule too far into the future? */ + if (unlikely((start + sched->span) >= max)) { + status = -EFBIG; + goto fail; + } ++ stream->next_uframe = start; + goto ready; + } + +@@ -1386,10 +1457,6 @@ + + /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ + +- period = urb->interval; +- if (!stream->highspeed) +- period <<= 3; +- + /* find a uframe slot with enough bandwidth */ + for (; start < (stream->next_uframe + period); start++) { + int enough_space; +@@ -1486,13 +1553,27 @@ + static inline void + itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) + { +- /* always prepend ITD/SITD ... only QH tree is order-sensitive */ +- itd->itd_next = ehci->pshadow [frame]; +- itd->hw_next = ehci->periodic [frame]; +- ehci->pshadow [frame].itd = itd; ++ union ehci_shadow *prev = &ehci->pshadow[frame]; ++ __hc32 *hw_p = &ehci->periodic[frame]; ++ union ehci_shadow here = *prev; ++ __hc32 type = 0; ++ ++ /* skip any iso nodes which might belong to previous microframes */ ++ while (here.ptr) { ++ type = Q_NEXT_TYPE(ehci, *hw_p); ++ if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) ++ break; ++ prev = periodic_next_shadow(ehci, prev, type); ++ hw_p = shadow_next_periodic(ehci, &here, type); ++ here = *prev; ++ } ++ ++ itd->itd_next = here; ++ itd->hw_next = *hw_p; ++ prev->itd = itd; + itd->frame = frame; + wmb (); +- ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); ++ *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); + } + + /* fit urb's itds into the selected schedule slot; activate as needed */ +@@ -2046,13 +2127,27 @@ + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); + } + iso_stream_put (ehci, stream); +- /* OK to recycle this SITD now that its completion callback ran. */ ++ + done: + sitd->urb = NULL; +- sitd->stream = NULL; +- list_move(&sitd->sitd_list, &stream->free_list); +- iso_stream_put(ehci, stream); +- ++ if (ehci->clock_frame != sitd->frame) { ++ /* OK to recycle this SITD now. */ ++ sitd->stream = NULL; ++ list_move(&sitd->sitd_list, &stream->free_list); ++ iso_stream_put(ehci, stream); ++ } else { ++ /* HW might remember this SITD, so we can't recycle it yet. ++ * Move it to a safe place until a new frame starts. ++ */ ++ list_move(&sitd->sitd_list, &ehci->cached_sitd_list); ++ if (stream->refcount == 2) { ++ /* If iso_stream_put() were called here, stream ++ * would be freed. Instead, just prevent reuse. ++ */ ++ stream->ep->hcpriv = NULL; ++ stream->ep = NULL; ++ } ++ } + return retval; + } + +@@ -2118,9 +2213,10 @@ + + /*-------------------------------------------------------------------------*/ + +-static void free_cached_itd_list(struct ehci_hcd *ehci) ++static void free_cached_lists(struct ehci_hcd *ehci) + { + struct ehci_itd *itd, *n; ++ struct ehci_sitd *sitd, *sn; + + list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { + struct ehci_iso_stream *stream = itd->stream; +@@ -2128,6 +2224,13 @@ + list_move(&itd->itd_list, &stream->free_list); + iso_stream_put(ehci, stream); + } ++ ++ list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { ++ struct ehci_iso_stream *stream = sitd->stream; ++ sitd->stream = NULL; ++ list_move(&sitd->sitd_list, &stream->free_list); ++ iso_stream_put(ehci, stream); ++ } + } + + /*-------------------------------------------------------------------------*/ +@@ -2154,7 +2257,7 @@ + clock_frame = -1; + } + if (ehci->clock_frame != clock_frame) { +- free_cached_itd_list(ehci); ++ free_cached_lists(ehci); + ehci->clock_frame = clock_frame; + } + clock %= mod; +@@ -2185,10 +2288,11 @@ + case Q_TYPE_QH: + /* handle any completions */ + temp.qh = qh_get (q.qh); +- type = Q_NEXT_TYPE(ehci, q.qh->hw_next); ++ type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); + q = q.qh->qh_next; + modified = qh_completions (ehci, temp.qh); +- if (unlikely (list_empty (&temp.qh->qtd_list))) ++ if (unlikely(list_empty(&temp.qh->qtd_list) || ++ temp.qh->needs_rescan)) + intr_deschedule (ehci, temp.qh); + qh_put (temp.qh); + break; +@@ -2316,7 +2420,7 @@ + clock = now; + clock_frame = clock >> 3; + if (ehci->clock_frame != clock_frame) { +- free_cached_itd_list(ehci); ++ free_cached_lists(ehci); + ehci->clock_frame = clock_frame; + } + } else { +diff -ur linux-2.6.30.9/drivers/usb/host/hwa-hc.c linux-2.6.32.27/drivers/usb/host/hwa-hc.c +--- linux-2.6.30.9/drivers/usb/host/hwa-hc.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/hwa-hc.c 2010-12-09 23:29:45.000000000 +0200 +@@ -172,25 +172,6 @@ + + } + +-static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) +-{ +- struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); +- struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); +- dev_err(wusbhc->dev, "%s (%p [%p], 0x%lx) UNIMPLEMENTED\n", __func__, +- usb_hcd, hwahc, *(unsigned long *) &msg); +- return -ENOSYS; +-} +- +-static int hwahc_op_resume(struct usb_hcd *usb_hcd) +-{ +- struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); +- struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); +- +- dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, +- usb_hcd, hwahc); +- return -ENOSYS; +-} +- + /* + * No need to abort pipes, as when this is called, all the children + * has been disconnected and that has done it [through +@@ -598,8 +579,6 @@ + .flags = HCD_USB2, /* FIXME */ + .reset = hwahc_op_reset, + .start = hwahc_op_start, +- .pci_suspend = hwahc_op_suspend, +- .pci_resume = hwahc_op_resume, + .stop = hwahc_op_stop, + .get_frame_number = hwahc_op_get_frame_number, + .urb_enqueue = hwahc_op_urb_enqueue, +diff -ur linux-2.6.30.9/drivers/usb/host/ohci-dbg.c linux-2.6.32.27/drivers/usb/host/ohci-dbg.c +--- linux-2.6.30.9/drivers/usb/host/ohci-dbg.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci-dbg.c 2010-12-09 23:29:45.000000000 +0200 +@@ -431,7 +431,7 @@ + + struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ +- struct device *dev; ++ struct ohci_hcd *ohci; + struct mutex mutex; /* protect filling of buffer */ + size_t count; /* number of characters filled into buffer */ + char *page; +@@ -505,15 +505,11 @@ + + static ssize_t fill_async_buffer(struct debug_buffer *buf) + { +- struct usb_bus *bus; +- struct usb_hcd *hcd; + struct ohci_hcd *ohci; + size_t temp; + unsigned long flags; + +- bus = dev_get_drvdata(buf->dev); +- hcd = bus_to_hcd(bus); +- ohci = hcd_to_ohci(hcd); ++ ohci = buf->ohci; + + /* display control and bulk lists together, for simplicity */ + spin_lock_irqsave (&ohci->lock, flags); +@@ -529,8 +525,6 @@ + + static ssize_t fill_periodic_buffer(struct debug_buffer *buf) + { +- struct usb_bus *bus; +- struct usb_hcd *hcd; + struct ohci_hcd *ohci; + struct ed **seen, *ed; + unsigned long flags; +@@ -542,9 +536,7 @@ + return 0; + seen_count = 0; + +- bus = (struct usb_bus *)dev_get_drvdata(buf->dev); +- hcd = bus_to_hcd(bus); +- ohci = hcd_to_ohci(hcd); ++ ohci = buf->ohci; + next = buf->page; + size = PAGE_SIZE; + +@@ -626,7 +618,6 @@ + + static ssize_t fill_registers_buffer(struct debug_buffer *buf) + { +- struct usb_bus *bus; + struct usb_hcd *hcd; + struct ohci_hcd *ohci; + struct ohci_regs __iomem *regs; +@@ -635,9 +626,8 @@ + char *next; + u32 rdata; + +- bus = (struct usb_bus *)dev_get_drvdata(buf->dev); +- hcd = bus_to_hcd(bus); +- ohci = hcd_to_ohci(hcd); ++ ohci = buf->ohci; ++ hcd = ohci_to_hcd(ohci); + regs = ohci->regs; + next = buf->page; + size = PAGE_SIZE; +@@ -710,7 +700,7 @@ + return PAGE_SIZE - size; + } + +-static struct debug_buffer *alloc_buffer(struct device *dev, ++static struct debug_buffer *alloc_buffer(struct ohci_hcd *ohci, + ssize_t (*fill_func)(struct debug_buffer *)) + { + struct debug_buffer *buf; +@@ -718,7 +708,7 @@ + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + + if (buf) { +- buf->dev = dev; ++ buf->ohci = ohci; + buf->fill_func = fill_func; + mutex_init(&buf->mutex); + } +@@ -810,26 +800,25 @@ + static inline void create_debug_files (struct ohci_hcd *ohci) + { + struct usb_bus *bus = &ohci_to_hcd(ohci)->self; +- struct device *dev = bus->dev; + + ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root); + if (!ohci->debug_dir) + goto dir_error; + + ohci->debug_async = debugfs_create_file("async", S_IRUGO, +- ohci->debug_dir, dev, ++ ohci->debug_dir, ohci, + &debug_async_fops); + if (!ohci->debug_async) + goto async_error; + + ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, +- ohci->debug_dir, dev, ++ ohci->debug_dir, ohci, + &debug_periodic_fops); + if (!ohci->debug_periodic) + goto periodic_error; + + ohci->debug_registers = debugfs_create_file("registers", S_IRUGO, +- ohci->debug_dir, dev, ++ ohci->debug_dir, ohci, + &debug_registers_fops); + if (!ohci->debug_registers) + goto registers_error; +diff -ur linux-2.6.30.9/drivers/usb/host/ohci.h linux-2.6.32.27/drivers/usb/host/ohci.h +--- linux-2.6.30.9/drivers/usb/host/ohci.h 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci.h 2010-12-09 23:29:45.000000000 +0200 +@@ -402,6 +402,7 @@ + #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ + #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ + #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ ++#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ + // there are also chip quirks/bugs in init logic + + struct work_struct nec_work; /* Worker for NEC quirk */ +@@ -433,6 +434,10 @@ + { + return ohci->flags & OHCI_QUIRK_AMD_ISO; + } ++static inline int quirk_amdprefetch(struct ohci_hcd *ohci) ++{ ++ return ohci->flags & OHCI_QUIRK_AMD_PREFETCH; ++} + #else + static inline int quirk_nec(struct ohci_hcd *ohci) + { +@@ -446,6 +451,10 @@ + { + return 0; + } ++static inline int quirk_amdprefetch(struct ohci_hcd *ohci) ++{ ++ return 0; ++} + #endif + + /* convert between an hcd pointer and the corresponding ohci_hcd */ +diff -ur linux-2.6.30.9/drivers/usb/host/ohci-hcd.c linux-2.6.32.27/drivers/usb/host/ohci-hcd.c +--- linux-2.6.30.9/drivers/usb/host/ohci-hcd.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci-hcd.c 2010-12-09 23:29:45.000000000 +0200 +@@ -34,7 +34,6 @@ + #include <linux/usb/otg.h> + #include <linux/dma-mapping.h> + #include <linux/dmapool.h> +-#include <linux/reboot.h> + #include <linux/workqueue.h> + #include <linux/debugfs.h> + +@@ -88,6 +87,7 @@ + #ifdef CONFIG_PCI + static void quirk_amd_pll(int state); + static void amd_iso_dev_put(void); ++static void sb800_prefetch(struct ohci_hcd *ohci, int on); + #else + static inline void quirk_amd_pll(int state) + { +@@ -97,6 +97,10 @@ + { + return; + } ++static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) ++{ ++ return; ++} + #endif + + +@@ -571,7 +575,7 @@ + */ + static int ohci_run (struct ohci_hcd *ohci) + { +- u32 mask, temp; ++ u32 mask, val; + int first = ohci->fminterval == 0; + struct usb_hcd *hcd = ohci_to_hcd(ohci); + +@@ -580,8 +584,8 @@ + /* boot firmware should have set this up (5.1.1.3.1) */ + if (first) { + +- temp = ohci_readl (ohci, &ohci->regs->fminterval); +- ohci->fminterval = temp & 0x3fff; ++ val = ohci_readl (ohci, &ohci->regs->fminterval); ++ ohci->fminterval = val & 0x3fff; + if (ohci->fminterval != FI) + ohci_dbg (ohci, "fminterval delta %d\n", + ohci->fminterval - FI); +@@ -600,25 +604,25 @@ + + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: +- temp = 0; ++ val = 0; + break; + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESUME; +- temp = 10 /* msec wait */; ++ val = 10 /* msec wait */; + break; + // case OHCI_USB_RESET: + default: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESET; +- temp = 50 /* msec wait */; ++ val = 50 /* msec wait */; + break; + } + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + // flush the writes + (void) ohci_readl (ohci, &ohci->regs->control); +- msleep(temp); ++ msleep(val); + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + +@@ -628,9 +632,9 @@ + retry: + /* HC Reset requires max 10 us delay */ + ohci_writel (ohci, OHCI_HCR, &ohci->regs->cmdstatus); +- temp = 30; /* ... allow extra time */ ++ val = 30; /* ... allow extra time */ + while ((ohci_readl (ohci, &ohci->regs->cmdstatus) & OHCI_HCR) != 0) { +- if (--temp == 0) { ++ if (--val == 0) { + spin_unlock_irq (&ohci->lock); + ohci_err (ohci, "USB HC reset timed out!\n"); + return -1; +@@ -699,23 +703,23 @@ + ohci_writel (ohci, mask, &ohci->regs->intrenable); + + /* handle root hub init quirks ... */ +- temp = roothub_a (ohci); +- temp &= ~(RH_A_PSM | RH_A_OCPM); ++ val = roothub_a (ohci); ++ val &= ~(RH_A_PSM | RH_A_OCPM); + if (ohci->flags & OHCI_QUIRK_SUPERIO) { + /* NSC 87560 and maybe others */ +- temp |= RH_A_NOCP; +- temp &= ~(RH_A_POTPGT | RH_A_NPS); +- ohci_writel (ohci, temp, &ohci->regs->roothub.a); ++ val |= RH_A_NOCP; ++ val &= ~(RH_A_POTPGT | RH_A_NPS); ++ ohci_writel (ohci, val, &ohci->regs->roothub.a); + } else if ((ohci->flags & OHCI_QUIRK_AMD756) || + (ohci->flags & OHCI_QUIRK_HUB_POWER)) { + /* hub power always on; required for AMD-756 and some + * Mac platforms. ganged overcurrent reporting, if any. + */ +- temp |= RH_A_NPS; +- ohci_writel (ohci, temp, &ohci->regs->roothub.a); ++ val |= RH_A_NPS; ++ ohci_writel (ohci, val, &ohci->regs->roothub.a); + } + ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status); +- ohci_writel (ohci, (temp & RH_A_NPS) ? 0 : RH_B_PPCM, ++ ohci_writel (ohci, (val & RH_A_NPS) ? 0 : RH_B_PPCM, + &ohci->regs->roothub.b); + // flush those writes + (void) ohci_readl (ohci, &ohci->regs->control); +@@ -724,7 +728,7 @@ + spin_unlock_irq (&ohci->lock); + + // POTPGT delay is bits 24-31, in 2 ms units. +- mdelay ((temp >> 23) & 0x1fe); ++ mdelay ((val >> 23) & 0x1fe); + hcd->state = HC_STATE_RUNNING; + + if (quirk_zfmicro(ohci)) { +@@ -1105,7 +1109,7 @@ + set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + + #ifdef DEBUG +- ohci_debug_root = debugfs_create_dir("ohci", NULL); ++ ohci_debug_root = debugfs_create_dir("ohci", usb_debug_root); + if (!ohci_debug_root) { + retval = -ENOENT; + goto error_debug; +diff -ur linux-2.6.30.9/drivers/usb/host/ohci-hub.c linux-2.6.32.27/drivers/usb/host/ohci-hub.c +--- linux-2.6.30.9/drivers/usb/host/ohci-hub.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci-hub.c 2010-12-09 23:29:45.000000000 +0200 +@@ -697,7 +697,7 @@ + u16 wLength + ) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); +- int ports = hcd_to_bus (hcd)->root_hub->maxchild; ++ int ports = ohci->num_ports; + u32 temp; + int retval = 0; + +diff -ur linux-2.6.30.9/drivers/usb/host/ohci-pci.c linux-2.6.32.27/drivers/usb/host/ohci-pci.c +--- linux-2.6.30.9/drivers/usb/host/ohci-pci.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci-pci.c 2010-12-09 23:29:45.000000000 +0200 +@@ -177,6 +177,13 @@ + return 0; + + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); ++ ++ /* SB800 needs pre-fetch fix */ ++ if ((rev >= 0x40) && (rev <= 0x4f)) { ++ ohci->flags |= OHCI_QUIRK_AMD_PREFETCH; ++ ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); ++ } ++ + if ((rev > 0x3b) || (rev < 0x30)) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; +@@ -262,6 +269,19 @@ + + } + ++static void sb800_prefetch(struct ohci_hcd *ohci, int on) ++{ ++ struct pci_dev *pdev; ++ u16 misc; ++ ++ pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); ++ pci_read_config_word(pdev, 0x50, &misc); ++ if (on == 0) ++ pci_write_config_word(pdev, 0x50, misc & 0xfcff); ++ else ++ pci_write_config_word(pdev, 0x50, misc | 0x0300); ++} ++ + /* List of quirks for OHCI */ + static const struct pci_device_id ohci_pci_quirks[] = { + { +@@ -372,7 +392,7 @@ + + #ifdef CONFIG_PM + +-static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) ++static int ohci_pci_suspend(struct usb_hcd *hcd) + { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; +@@ -394,10 +414,6 @@ + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); + +- /* make sure snapshot being resumed re-enumerates everything */ +- if (message.event == PM_EVENT_PRETHAW) +- ohci_usb_reset(ohci); +- + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ohci->lock, flags); +@@ -406,9 +422,14 @@ + } + + +-static int ohci_pci_resume (struct usb_hcd *hcd) ++static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated) + { + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ++ /* Make sure resume from hibernation re-enumerates everything */ ++ if (hibernated) ++ ohci_usb_reset(hcd_to_ohci(hcd)); ++ + ohci_finish_controller_resume(hcd); + return 0; + } +@@ -484,12 +505,11 @@ + + .probe = usb_hcd_pci_probe, + .remove = usb_hcd_pci_remove, ++ .shutdown = usb_hcd_pci_shutdown, + +-#ifdef CONFIG_PM +- .suspend = usb_hcd_pci_suspend, +- .resume = usb_hcd_pci_resume, ++#ifdef CONFIG_PM_SLEEP ++ .driver = { ++ .pm = &usb_hcd_pci_pm_ops ++ }, + #endif +- +- .shutdown = usb_hcd_pci_shutdown, + }; +- +diff -ur linux-2.6.30.9/drivers/usb/host/ohci-q.c linux-2.6.32.27/drivers/usb/host/ohci-q.c +--- linux-2.6.30.9/drivers/usb/host/ohci-q.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/ohci-q.c 2010-12-09 23:29:45.000000000 +0200 +@@ -49,9 +49,12 @@ + switch (usb_pipetype (urb->pipe)) { + case PIPE_ISOCHRONOUS: + ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--; +- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 +- && quirk_amdiso(ohci)) +- quirk_amd_pll(1); ++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { ++ if (quirk_amdiso(ohci)) ++ quirk_amd_pll(1); ++ if (quirk_amdprefetch(ohci)) ++ sb800_prefetch(ohci, 0); ++ } + break; + case PIPE_INTERRUPT: + ohci_to_hcd(ohci)->self.bandwidth_int_reqs--; +@@ -418,7 +421,7 @@ + is_out = !(ep->desc.bEndpointAddress & USB_DIR_IN); + + /* FIXME usbcore changes dev->devnum before SET_ADDRESS +- * suceeds ... otherwise we wouldn't need "pipe". ++ * succeeds ... otherwise we wouldn't need "pipe". + */ + info = usb_pipedevice (pipe); + ed->type = usb_pipetype(pipe); +@@ -680,9 +683,12 @@ + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } +- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0 +- && quirk_amdiso(ohci)) +- quirk_amd_pll(0); ++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) { ++ if (quirk_amdiso(ohci)) ++ quirk_amd_pll(0); ++ if (quirk_amdprefetch(ohci)) ++ sb800_prefetch(ohci, 1); ++ } + periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 + && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; + break; +diff -ur linux-2.6.30.9/drivers/usb/host/pci-quirks.c linux-2.6.32.27/drivers/usb/host/pci-quirks.c +--- linux-2.6.30.9/drivers/usb/host/pci-quirks.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/pci-quirks.c 2010-12-09 23:29:45.000000000 +0200 +@@ -15,6 +15,7 @@ + #include <linux/delay.h> + #include <linux/acpi.h> + #include "pci-quirks.h" ++#include "xhci-ext-caps.h" + + + #define UHCI_USBLEGSUP 0xc0 /* legacy support */ +@@ -341,7 +342,127 @@ + return; + } + ++/* ++ * handshake - spin reading a register until handshake completes ++ * @ptr: address of hc register to be read ++ * @mask: bits to look at in result of read ++ * @done: value of those bits when handshake succeeds ++ * @wait_usec: timeout in microseconds ++ * @delay_usec: delay in microseconds to wait between polling ++ * ++ * Polls a register every delay_usec microseconds. ++ * Returns 0 when the mask bits have the value done. ++ * Returns -ETIMEDOUT if this condition is not true after ++ * wait_usec microseconds have passed. ++ */ ++static int handshake(void __iomem *ptr, u32 mask, u32 done, ++ int wait_usec, int delay_usec) ++{ ++ u32 result; ++ ++ do { ++ result = readl(ptr); ++ result &= mask; ++ if (result == done) ++ return 0; ++ udelay(delay_usec); ++ wait_usec -= delay_usec; ++ } while (wait_usec > 0); ++ return -ETIMEDOUT; ++} ++ ++/** ++ * PCI Quirks for xHCI. ++ * ++ * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. ++ * It signals to the BIOS that the OS wants control of the host controller, ++ * and then waits 5 seconds for the BIOS to hand over control. ++ * If we timeout, assume the BIOS is broken and take control anyway. ++ */ ++static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) ++{ ++ void __iomem *base; ++ int ext_cap_offset; ++ void __iomem *op_reg_base; ++ u32 val; ++ int timeout; ++ ++ if (!mmio_resource_enabled(pdev, 0)) ++ return; ++ ++ base = ioremap_nocache(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ if (base == NULL) ++ return; + ++ /* ++ * Find the Legacy Support Capability register - ++ * this is optional for xHCI host controllers. ++ */ ++ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); ++ do { ++ if (!ext_cap_offset) ++ /* We've reached the end of the extended capabilities */ ++ goto hc_init; ++ val = readl(base + ext_cap_offset); ++ if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) ++ break; ++ ext_cap_offset = xhci_find_next_cap_offset(base, ext_cap_offset); ++ } while (1); ++ ++ /* If the BIOS owns the HC, signal that the OS wants it, and wait */ ++ if (val & XHCI_HC_BIOS_OWNED) { ++ writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset); ++ ++ /* Wait for 5 seconds with 10 microsecond polling interval */ ++ timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, ++ 0, 5000, 10); ++ ++ /* Assume a buggy BIOS and take HC ownership anyway */ ++ if (timeout) { ++ dev_warn(&pdev->dev, "xHCI BIOS handoff failed" ++ " (BIOS bug ?) %08x\n", val); ++ writel(val & ~XHCI_HC_BIOS_OWNED, base + ext_cap_offset); ++ } ++ } ++ ++ /* Disable any BIOS SMIs */ ++ writel(XHCI_LEGACY_DISABLE_SMI, ++ base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); ++ ++hc_init: ++ op_reg_base = base + XHCI_HC_LENGTH(readl(base)); ++ ++ /* Wait for the host controller to be ready before writing any ++ * operational or runtime registers. Wait 5 seconds and no more. ++ */ ++ timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, ++ 5000, 10); ++ /* Assume a buggy HC and start HC initialization anyway */ ++ if (timeout) { ++ val = readl(op_reg_base + XHCI_STS_OFFSET); ++ dev_warn(&pdev->dev, ++ "xHCI HW not ready after 5 sec (HC bug?) " ++ "status = 0x%x\n", val); ++ } ++ ++ /* Send the halt and disable interrupts command */ ++ val = readl(op_reg_base + XHCI_CMD_OFFSET); ++ val &= ~(XHCI_CMD_RUN | XHCI_IRQS); ++ writel(val, op_reg_base + XHCI_CMD_OFFSET); ++ ++ /* Wait for the HC to halt - poll every 125 usec (one microframe). */ ++ timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_HALT, 1, ++ XHCI_MAX_HALT_USEC, 125); ++ if (timeout) { ++ val = readl(op_reg_base + XHCI_STS_OFFSET); ++ dev_warn(&pdev->dev, ++ "xHCI HW did not halt within %d usec " ++ "status = 0x%x\n", XHCI_MAX_HALT_USEC, val); ++ } ++ ++ iounmap(base); ++} + + static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) + { +@@ -351,5 +472,7 @@ + quirk_usb_handoff_ohci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI) + quirk_usb_disable_ehci(pdev); ++ else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) ++ quirk_usb_handoff_xhci(pdev); + } + DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); +diff -ur linux-2.6.30.9/drivers/usb/host/uhci-hcd.c linux-2.6.32.27/drivers/usb/host/uhci-hcd.c +--- linux-2.6.30.9/drivers/usb/host/uhci-hcd.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/uhci-hcd.c 2010-12-09 23:29:45.000000000 +0200 +@@ -67,7 +67,7 @@ + * debug = 0, no debugging messages + * debug = 1, dump failed URBs except for stalls + * debug = 2, dump all failed URBs (including stalls) +- * show all queues in /debug/uhci/[pci_addr] ++ * show all queues in /sys/kernel/debug/uhci/[pci_addr] + * debug = 3, show all TDs in URBs when dumping + */ + #ifdef DEBUG +@@ -735,6 +735,7 @@ + uhci_hc_died(uhci); + uhci_scan_schedule(uhci); + spin_unlock_irq(&uhci->lock); ++ synchronize_irq(hcd->irq); + + del_timer_sync(&uhci->fsbr_timer); + release_uhci(uhci); +@@ -749,7 +750,20 @@ + spin_lock_irq(&uhci->lock); + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + rc = -ESHUTDOWN; +- else if (!uhci->dead) ++ else if (uhci->dead) ++ ; /* Dead controllers tell no tales */ ++ ++ /* Once the controller is stopped, port resumes that are already ++ * in progress won't complete. Hence if remote wakeup is enabled ++ * for the root hub and any ports are in the middle of a resume or ++ * remote wakeup, we must fail the suspend. ++ */ ++ else if (hcd->self.root_hub->do_remote_wakeup && ++ uhci->resuming_ports) { ++ dev_dbg(uhci_dev(uhci), "suspend failed because a port " ++ "is resuming\n"); ++ rc = -EBUSY; ++ } else + suspend_rh(uhci, UHCI_RH_SUSPENDED); + spin_unlock_irq(&uhci->lock); + return rc; +@@ -769,7 +783,7 @@ + return rc; + } + +-static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) ++static int uhci_pci_suspend(struct usb_hcd *hcd) + { + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + int rc = 0; +@@ -795,10 +809,6 @@ + + /* FIXME: Enable non-PME# remote wakeup? */ + +- /* make sure snapshot being resumed re-enumerates everything */ +- if (message.event == PM_EVENT_PRETHAW) +- uhci_hc_died(uhci); +- + done_okay: + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + done: +@@ -806,7 +816,7 @@ + return rc; + } + +-static int uhci_pci_resume(struct usb_hcd *hcd) ++static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) + { + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + +@@ -820,6 +830,10 @@ + + spin_lock_irq(&uhci->lock); + ++ /* Make sure resume from hibernation re-enumerates everything */ ++ if (hibernated) ++ uhci_hc_died(uhci); ++ + /* FIXME: Disable non-PME# remote wakeup? */ + + /* The firmware or a boot kernel may have changed the controller +@@ -940,10 +954,11 @@ + .remove = usb_hcd_pci_remove, + .shutdown = uhci_shutdown, + +-#ifdef CONFIG_PM +- .suspend = usb_hcd_pci_suspend, +- .resume = usb_hcd_pci_resume, +-#endif /* PM */ ++#ifdef CONFIG_PM_SLEEP ++ .driver = { ++ .pm = &usb_hcd_pci_pm_ops ++ }, ++#endif + }; + + static int __init uhci_hcd_init(void) +@@ -961,7 +976,7 @@ + errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); + if (!errbuf) + goto errbuf_failed; +- uhci_debugfs_root = debugfs_create_dir("uhci", NULL); ++ uhci_debugfs_root = debugfs_create_dir("uhci", usb_debug_root); + if (!uhci_debugfs_root) + goto debug_failed; + } +diff -ur linux-2.6.30.9/drivers/usb/host/uhci-hub.c linux-2.6.32.27/drivers/usb/host/uhci-hub.c +--- linux-2.6.30.9/drivers/usb/host/uhci-hub.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/uhci-hub.c 2010-12-09 23:29:45.000000000 +0200 +@@ -167,7 +167,7 @@ + /* Port received a wakeup request */ + set_bit(port, &uhci->resuming_ports); + uhci->ports_timeout = jiffies + +- msecs_to_jiffies(20); ++ msecs_to_jiffies(25); + + /* Make sure we see the port again + * after the resuming period is over. */ +diff -ur linux-2.6.30.9/drivers/usb/host/uhci-q.c linux-2.6.32.27/drivers/usb/host/uhci-q.c +--- linux-2.6.30.9/drivers/usb/host/uhci-q.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/uhci-q.c 2010-12-09 23:29:45.000000000 +0200 +@@ -260,7 +260,7 @@ + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ +- qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; ++ qh->type = usb_endpoint_type(&hep->desc); + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { +@@ -1422,7 +1422,6 @@ + goto err_submit_failed; + + /* Add this URB to the QH */ +- urbp->qh = qh; + list_add_tail(&urbp->node, &qh->queue); + + /* If the new URB is the first and only one on this QH then either +diff -ur linux-2.6.30.9/drivers/usb/host/whci/asl.c linux-2.6.32.27/drivers/usb/host/whci/asl.c +--- linux-2.6.30.9/drivers/usb/host/whci/asl.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/asl.c 2010-12-09 23:29:45.000000000 +0200 +@@ -115,6 +115,10 @@ + if (status & QTD_STS_HALTED) { + /* Ug, an error. */ + process_halted_qtd(whc, qset, td); ++ /* A halted qTD always triggers an update ++ because the qset was either removed or ++ reactivated. */ ++ update |= WHC_UPDATE_UPDATED; + goto done; + } + +@@ -227,11 +231,21 @@ + /* + * Now that the ASL is updated, complete the removal of any + * removed qsets. ++ * ++ * If the qset was to be reset, do so and reinsert it into the ++ * ASL if it has pending transfers. + */ + spin_lock_irq(&whc->lock); + + list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { + qset_remove_complete(whc, qset); ++ if (qset->reset) { ++ qset_reset(whc, qset); ++ if (!list_empty(&qset->stds)) { ++ asl_qset_insert_begin(whc, qset); ++ queue_work(whc->workqueue, &whc->async_work); ++ } ++ } + } + + spin_unlock_irq(&whc->lock); +@@ -267,7 +281,7 @@ + else + err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); + if (!err) { +- if (!qset->in_sw_list) ++ if (!qset->in_sw_list && !qset->remove) + asl_qset_insert_begin(whc, qset); + } else + usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); +@@ -295,6 +309,7 @@ + struct whc_urb *wurb = urb->hcpriv; + struct whc_qset *qset = wurb->qset; + struct whc_std *std, *t; ++ bool has_qtd = false; + int ret; + unsigned long flags; + +@@ -305,17 +320,21 @@ + goto out; + + list_for_each_entry_safe(std, t, &qset->stds, list_node) { +- if (std->urb == urb) ++ if (std->urb == urb) { ++ if (std->qtd) ++ has_qtd = true; + qset_free_std(whc, std); +- else ++ } else + std->qtd = NULL; /* so this std is re-added when the qset is */ + } + +- asl_qset_remove(whc, qset); +- wurb->status = status; +- wurb->is_async = true; +- queue_work(whc->workqueue, &wurb->dequeue_work); +- ++ if (has_qtd) { ++ asl_qset_remove(whc, qset); ++ wurb->status = status; ++ wurb->is_async = true; ++ queue_work(whc->workqueue, &wurb->dequeue_work); ++ } else ++ qset_remove_urb(whc, qset, urb, status); + out: + spin_unlock_irqrestore(&whc->lock, flags); + +diff -ur linux-2.6.30.9/drivers/usb/host/whci/debug.c linux-2.6.32.27/drivers/usb/host/whci/debug.c +--- linux-2.6.30.9/drivers/usb/host/whci/debug.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/debug.c 2010-12-09 23:29:45.000000000 +0200 +@@ -134,7 +134,7 @@ + return single_open(file, pzl_print, inode->i_private); + } + +-static struct file_operations di_fops = { ++static const struct file_operations di_fops = { + .open = di_open, + .read = seq_read, + .llseek = seq_lseek, +@@ -142,7 +142,7 @@ + .owner = THIS_MODULE, + }; + +-static struct file_operations asl_fops = { ++static const struct file_operations asl_fops = { + .open = asl_open, + .read = seq_read, + .llseek = seq_lseek, +@@ -150,7 +150,7 @@ + .owner = THIS_MODULE, + }; + +-static struct file_operations pzl_fops = { ++static const struct file_operations pzl_fops = { + .open = pzl_open, + .read = seq_read, + .llseek = seq_lseek, +diff -ur linux-2.6.30.9/drivers/usb/host/whci/hcd.c linux-2.6.32.27/drivers/usb/host/whci/hcd.c +--- linux-2.6.30.9/drivers/usb/host/whci/hcd.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/hcd.c 2010-12-09 23:29:45.000000000 +0200 +@@ -192,19 +192,23 @@ + struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); + struct whc *whc = wusbhc_to_whc(wusbhc); + struct whc_qset *qset; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&whc->lock, flags); + + qset = ep->hcpriv; + if (qset) { + qset->remove = 1; ++ qset->reset = 1; + + if (usb_endpoint_xfer_bulk(&ep->desc) + || usb_endpoint_xfer_control(&ep->desc)) + queue_work(whc->workqueue, &whc->async_work); + else + queue_work(whc->workqueue, &whc->periodic_work); +- +- qset_reset(whc, qset); + } ++ ++ spin_unlock_irqrestore(&whc->lock, flags); + } + + +diff -ur linux-2.6.30.9/drivers/usb/host/whci/pzl.c linux-2.6.32.27/drivers/usb/host/whci/pzl.c +--- linux-2.6.30.9/drivers/usb/host/whci/pzl.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/pzl.c 2010-12-09 23:29:45.000000000 +0200 +@@ -121,6 +121,10 @@ + if (status & QTD_STS_HALTED) { + /* Ug, an error. */ + process_halted_qtd(whc, qset, td); ++ /* A halted qTD always triggers an update ++ because the qset was either removed or ++ reactivated. */ ++ update |= WHC_UPDATE_UPDATED; + goto done; + } + +@@ -255,11 +259,21 @@ + /* + * Now that the PZL is updated, complete the removal of any + * removed qsets. ++ * ++ * If the qset was to be reset, do so and reinsert it into the ++ * PZL if it has pending transfers. + */ + spin_lock_irq(&whc->lock); + + list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) { + qset_remove_complete(whc, qset); ++ if (qset->reset) { ++ qset_reset(whc, qset); ++ if (!list_empty(&qset->stds)) { ++ qset_insert_in_sw_list(whc, qset); ++ queue_work(whc->workqueue, &whc->periodic_work); ++ } ++ } + } + + spin_unlock_irq(&whc->lock); +@@ -295,7 +309,7 @@ + else + err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); + if (!err) { +- if (!qset->in_sw_list) ++ if (!qset->in_sw_list && !qset->remove) + qset_insert_in_sw_list(whc, qset); + } else + usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); +@@ -323,6 +337,7 @@ + struct whc_urb *wurb = urb->hcpriv; + struct whc_qset *qset = wurb->qset; + struct whc_std *std, *t; ++ bool has_qtd = false; + int ret; + unsigned long flags; + +@@ -333,17 +348,22 @@ + goto out; + + list_for_each_entry_safe(std, t, &qset->stds, list_node) { +- if (std->urb == urb) ++ if (std->urb == urb) { ++ if (std->qtd) ++ has_qtd = true; + qset_free_std(whc, std); +- else ++ } else + std->qtd = NULL; /* so this std is re-added when the qset is */ + } + +- pzl_qset_remove(whc, qset); +- wurb->status = status; +- wurb->is_async = false; +- queue_work(whc->workqueue, &wurb->dequeue_work); +- ++ if (has_qtd) { ++ pzl_qset_remove(whc, qset); ++ update_pzl_hw_view(whc); ++ wurb->status = status; ++ wurb->is_async = false; ++ queue_work(whc->workqueue, &wurb->dequeue_work); ++ } else ++ qset_remove_urb(whc, qset, urb, status); + out: + spin_unlock_irqrestore(&whc->lock, flags); + +diff -ur linux-2.6.30.9/drivers/usb/host/whci/qset.c linux-2.6.32.27/drivers/usb/host/whci/qset.c +--- linux-2.6.30.9/drivers/usb/host/whci/qset.c 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/qset.c 2010-12-09 23:29:45.000000000 +0200 +@@ -103,7 +103,6 @@ + void qset_clear(struct whc *whc, struct whc_qset *qset) + { + qset->td_start = qset->td_end = qset->ntds = 0; +- qset->remove = 0; + + qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); + qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; +@@ -125,7 +124,7 @@ + */ + void qset_reset(struct whc *whc, struct whc_qset *qset) + { +- wait_for_completion(&qset->remove_complete); ++ qset->reset = 0; + + qset->qh.status &= ~QH_STATUS_SEQ_MASK; + qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); +@@ -156,6 +155,7 @@ + + void qset_remove_complete(struct whc *whc, struct whc_qset *qset) + { ++ qset->remove = 0; + list_del_init(&qset->list_node); + complete(&qset->remove_complete); + } +diff -ur linux-2.6.30.9/drivers/usb/host/whci/whci-hc.h linux-2.6.32.27/drivers/usb/host/whci/whci-hc.h +--- linux-2.6.30.9/drivers/usb/host/whci/whci-hc.h 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/drivers/usb/host/whci/whci-hc.h 2010-12-09 23:29:45.000000000 +0200 +@@ -264,6 +264,7 @@ + unsigned in_sw_list:1; + unsigned in_hw_list:1; + unsigned remove:1; ++ unsigned reset:1; + struct urb *pause_after_urb; + struct completion remove_complete; + int max_burst; +--- linux-2.6.30.9/include/linux/usb/ehci_def.h 2009-10-05 18:38:08.000000000 +0300 ++++ linux-2.6.32.27/include/linux/usb/ehci_def.h 2010-12-09 23:29:45.000000000 +0200 +@@ -105,6 +105,7 @@ + #define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ + #define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ + /* 19:16 for port testing */ ++#define PORT_TEST_PKT (0x4<<16) /* Port Test Control - packet test */ + #define PORT_LED_OFF (0<<14) + #define PORT_LED_AMBER (1<<14) + #define PORT_LED_GREEN (2<<14) +@@ -132,6 +133,19 @@ + #define USBMODE_CM_HC (3<<0) /* host controller mode */ + #define USBMODE_CM_IDLE (0<<0) /* idle state */ + ++/* Moorestown has some non-standard registers, partially due to the fact that ++ * its EHCI controller has both TT and LPM support. HOSTPCx are extentions to ++ * PORTSCx ++ */ ++#define HOSTPC0 0x84 /* HOSTPC extension */ ++#define HOSTPC_PHCD (1<<22) /* Phy clock disable */ ++#define HOSTPC_PSPD (3<<25) /* Port speed detection */ ++#define USBMODE_EX 0xc8 /* USB Device mode extension */ ++#define USBMODE_EX_VBPS (1<<5) /* VBus Power Select On */ ++#define USBMODE_EX_HC (3<<0) /* host controller mode */ ++#define TXFILLTUNING 0x24 /* TX FIFO Tuning register */ ++#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */ ++ + /* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) + */ +@@ -157,4 +171,25 @@ + #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) + } __attribute__ ((packed)); + ++#ifdef CONFIG_EARLY_PRINTK_DBGP ++#include <linux/init.h> ++extern int __init early_dbgp_init(char *s); ++extern struct console early_dbgp_console; ++#endif /* CONFIG_EARLY_PRINTK_DBGP */ ++ ++#ifdef CONFIG_EARLY_PRINTK_DBGP ++/* Call backs from ehci host driver to ehci debug driver */ ++extern int dbgp_external_startup(void); ++extern int dbgp_reset_prep(void); ++#else ++static inline int dbgp_reset_prep(void) ++{ ++ return 1; ++} ++static inline int dbgp_external_startup(void) ++{ ++ return -1; ++} ++#endif ++ + #endif /* __LINUX_USB_EHCI_DEF_H */ diff --git a/target/linux/realtek/patches-2.6.30/300-dont-ask-for-usb-serial-option-define.patch b/target/linux/realtek/patches-2.6.30/300-dont-ask-for-usb-serial-option-define.patch deleted file mode 100644 index 30047fd6a..000000000 --- a/target/linux/realtek/patches-2.6.30/300-dont-ask-for-usb-serial-option-define.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/drivers/usb/serial/usb-serial.c 2012-10-08 07:02:14.450118292 +0300 -+++ a/drivers/usb/serial/usb-serial.c 2012-10-08 07:02:24.720154214 +0300 -@@ -35,9 +35,7 @@ - #include <linux/usb/serial.h> - #include "pl2303.h" - --#if CONFIG_USB_SERIAL_OPTION - #include <linux/smp_lock.h> /* brucehou, 2010/05/21, for lock_kernel & unlock_kernel */ --#endif - - /* - * Version Information diff --git a/target/linux/realtek/patches-2.6.30/9995-net-rtl819x-include-paths.patch b/target/linux/realtek/patches-2.6.30/9995-net-rtl819x-include-paths.patch index 2710b56cc..239686707 100644 --- a/target/linux/realtek/patches-2.6.30/9995-net-rtl819x-include-paths.patch +++ b/target/linux/realtek/patches-2.6.30/9995-net-rtl819x-include-paths.patch @@ -370,17 +370,6 @@ #endif #ifdef CONFIG_RTL_PROC_DEBUG ---- a/drivers/usb/host/usb-rtl8652.h 2012-12-03 00:13:21.000000000 +0200 -+++ b/drivers/usb/host/usb-rtl8652.h 2013-02-06 02:05:03.071754444 +0200 -@@ -15,7 +15,7 @@ - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ --#include <bsp/bspchip.h> -+#include "../../../arch/rlx/bsp/bspchip.h" - #ifndef _USB_RTL8652_H - #define _USB_RTL8652_H - #define PADDR(addr) ((addr) & 0x1FFFFFFF) --- a/net/rtl/fastpath/fastpath_common.c 2013-02-04 03:15:32.875227255 +0200 +++ b/net/rtl/fastpath/fastpath_common.c 2013-02-06 02:09:07.638365005 +0200 @@ -6,7 +6,7 @@ |