xhci-mem.c: xhci_segment_free: No need for checking seg argument
[pandora-kernel.git] / drivers / usb / host / isp1760-hcd.c
index 840beda..5b08bd7 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/timer.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
 
@@ -39,7 +40,6 @@ struct isp1760_hcd {
        int                     int_done_map;
        struct memory_chunk memory_pool[BLOCKS];
        struct list_head        controlqhs, bulkqhs, interruptqhs;
-       int active_ptds;
 
        /* periodic schedule support */
 #define        DEFAULT_I_TDPS          1024
@@ -114,6 +114,7 @@ struct isp1760_qh {
        u32 toggle;
        u32 ping;
        int slot;
+       int tt_buffer_dirty;    /* See USB2.0 spec section 11.17.5 */
 };
 
 struct urb_listitem {
@@ -489,10 +490,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
                           16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
                           "analog" : "digital");
 
-       /* This is weird: at the first plug-in of a device there seems to be
-          one packet queued that never gets returned? */
-       priv->active_ptds = -1;
-
        /* ATL reset */
        reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET);
        mdelay(10);
@@ -514,83 +511,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
        return priv_init(hcd);
 }
 
-static void isp1760_init_maps(struct usb_hcd *hcd)
-{
-       /*set last maps, for iso its only 1, else 32 tds bitmap*/
-       reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000);
-       reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000);
-       reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001);
-
-       reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff);
-
-       reg_write32(hcd->regs, HC_BUFFER_STATUS_REG,
-                                               ATL_BUF_FILL | INT_BUF_FILL);
-}
-
-static void isp1760_enable_interrupts(struct usb_hcd *hcd)
-{
-       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff);
-       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0);
-       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff);
-       /* step 23 passed */
-}
-
-static int isp1760_run(struct usb_hcd *hcd)
-{
-       int retval;
-       u32 temp;
-       u32 command;
-       u32 chipid;
-
-       hcd->uses_new_polling = 1;
-
-       hcd->state = HC_STATE_RUNNING;
-       isp1760_enable_interrupts(hcd);
-       temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
-       reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN);
-
-       command = reg_read32(hcd->regs, HC_USBCMD);
-       command &= ~(CMD_LRESET|CMD_RESET);
-       command |= CMD_RUN;
-       reg_write32(hcd->regs, HC_USBCMD, command);
-
-       retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000);
-       if (retval)
-               return retval;
-
-       /*
-        * XXX
-        * Spec says to write FLAG_CF as last config action, priv code grabs
-        * the semaphore while doing so.
-        */
-       down_write(&ehci_cf_port_reset_rwsem);
-       reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF);
-
-       retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000);
-       up_write(&ehci_cf_port_reset_rwsem);
-       if (retval)
-               return retval;
-
-       chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
-       dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
-                                       chipid & 0xffff, chipid >> 16);
-
-       /* PTD Register Init Part 2, Step 28 */
-       /* enable INTs */
-       isp1760_init_maps(hcd);
-
-       /* GRR this is run-once init(), being done every time the HC starts.
-        * So long as they're part of class devices, we can't do it init()
-        * since the class device isn't created that early.
-        */
-       return 0;
-}
-
 static u32 base_to_chip(u32 base)
 {
        return ((base - 0x400) >> 3);
@@ -813,28 +733,29 @@ static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot,
        WARN_ON(slots[slot].qh);
        WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC);
 
-       slots[slot].qtd = qtd;
-       slots[slot].qh = qh;
-       qh->slot = slot;
-       qtd->status = QTD_XFER_STARTED; /* Set this before writing ptd, since
-               interrupt routine may preempt and expects this value. */
-       ptd_write(hcd->regs, ptd_offset, slot, ptd);
-       priv->active_ptds++;
-
        /* Make sure done map has not triggered from some unlinked transfer */
        if (ptd_offset == ATL_PTD_OFFSET) {
                priv->atl_done_map |= reg_read32(hcd->regs,
                                                HC_ATL_PTD_DONEMAP_REG);
-               priv->atl_done_map &= ~(1 << qh->slot);
+               priv->atl_done_map &= ~(1 << slot);
+       } else {
+               priv->int_done_map |= reg_read32(hcd->regs,
+                                               HC_INT_PTD_DONEMAP_REG);
+               priv->int_done_map &= ~(1 << slot);
+       }
 
+       qh->slot = slot;
+       qtd->status = QTD_XFER_STARTED;
+       slots[slot].timestamp = jiffies;
+       slots[slot].qtd = qtd;
+       slots[slot].qh = qh;
+       ptd_write(hcd->regs, ptd_offset, slot, ptd);
+
+       if (ptd_offset == ATL_PTD_OFFSET) {
                skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
                skip_map &= ~(1 << qh->slot);
                reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
        } else {
-               priv->int_done_map |= reg_read32(hcd->regs,
-                                               HC_INT_PTD_DONEMAP_REG);
-               priv->int_done_map &= ~(1 << qh->slot);
-
                skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
                skip_map &= ~(1 << qh->slot);
                reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
@@ -858,10 +779,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh,
                if (qtd->status < QTD_XFER_COMPLETE)
                        break;
 
-               if (list_is_last(&qtd->qtd_list, &qh->qtd_list))
-                       last_qtd = 1;
-               else
-                       last_qtd = qtd->urb != qtd_next->urb;
+               last_qtd = last_qtd_of_urb(qtd, qh);
 
                if ((!last_qtd) && (qtd->status == QTD_RETIRE))
                        qtd_next->status = QTD_RETIRE;
@@ -902,7 +820,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh,
                        urb_listitem = kmem_cache_zalloc(urb_listitem_cachep,
                                                                GFP_ATOMIC);
                        if (unlikely(!urb_listitem))
-                               break;
+                               break; /* Try again on next call */
                        urb_listitem->urb = qtd->urb;
                        list_add_tail(&urb_listitem->urb_list, urb_list);
                }
@@ -928,6 +846,10 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh)
                return;
        }
 
+       /* Make sure this endpoint's TT buffer is clean before queueing ptds */
+       if (qh->tt_buffer_dirty)
+               return;
+
        if (usb_pipeint(list_entry(qh->qtd_list.next, struct isp1760_qtd,
                                                        qtd_list)->urb->pipe)) {
                ptd_offset = INT_PTD_OFFSET;
@@ -1168,11 +1090,9 @@ static int check_atl_transfer(struct usb_hcd *hcd, struct ptd *ptd,
        return PTD_STATE_QTD_DONE;
 }
 
-static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
+static void handle_done_ptds(struct usb_hcd *hcd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
-       u32 imask;
-       irqreturn_t irqret = IRQ_NONE;
        struct ptd ptd;
        struct isp1760_qh *qh;
        int slot;
@@ -1181,27 +1101,14 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
        u32 ptd_offset;
        struct isp1760_qtd *qtd;
        int modified;
-       static int last_active_ptds;
-       int int_skip_map, atl_skip_map;
-
-       spin_lock(&priv->lock);
-
-       if (!(hcd->state & HC_STATE_RUNNING))
-               goto leave;
-
-       imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
-       if (unlikely(!imask))
-               goto leave;
-       reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */
+       int skip_map;
 
-       int_skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
-       atl_skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
-       priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
-       priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
-       priv->int_done_map &= ~int_skip_map;
-       priv->atl_done_map &= ~atl_skip_map;
+       skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
+       priv->int_done_map &= ~skip_map;
+       skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
+       priv->atl_done_map &= ~skip_map;
 
-       modified = priv->int_done_map | priv->atl_done_map;
+       modified = priv->int_done_map || priv->atl_done_map;
 
        while (priv->int_done_map || priv->atl_done_map) {
                if (priv->int_done_map) {
@@ -1240,7 +1147,6 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
                slots[slot].qtd = NULL;
                qh = slots[slot].qh;
                slots[slot].qh = NULL;
-               priv->active_ptds--;
                qh->slot = -1;
 
                WARN_ON(qtd->status != QTD_XFER_STARTED);
@@ -1281,6 +1187,15 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
 
                case PTD_STATE_URB_RETIRE:
                        qtd->status = QTD_RETIRE;
+                       if ((qtd->urb->dev->speed != USB_SPEED_HIGH) &&
+                                       (qtd->urb->status != -EPIPE) &&
+                                       (qtd->urb->status != -EREMOTEIO)) {
+                               qh->tt_buffer_dirty = 1;
+                               if (usb_hub_clear_tt_buffer(qtd->urb))
+                                       /* Clear failed; let's hope things work
+                                          anyway */
+                                       qh->tt_buffer_dirty = 0;
+                       }
                        qtd = NULL;
                        qh->toggle = 0;
                        qh->ping = 0;
@@ -1311,22 +1226,28 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
 
        if (modified)
                schedule_ptds(hcd);
+}
+
+static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
+{
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       u32 imask;
+       irqreturn_t irqret = IRQ_NONE;
 
-       /* ISP1760 Errata 2 explains that interrupts may be missed (or not
-          happen?) if two USB devices are running simultaneously. Perhaps
-          this happens when a PTD is finished during interrupt handling;
-          enable SOF interrupts if PTDs are still scheduled when exiting this
-          interrupt handler, just to be safe. */
+       spin_lock(&priv->lock);
 
-       if (priv->active_ptds != last_active_ptds) {
-               if (priv->active_ptds > 0)
-                       reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
-                                               INTERRUPT_ENABLE_SOT_MASK);
-               else
-                       reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
-                                               INTERRUPT_ENABLE_MASK);
-               last_active_ptds = priv->active_ptds;
-       }
+       if (!(hcd->state & HC_STATE_RUNNING))
+               goto leave;
+
+       imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
+       if (unlikely(!imask))
+               goto leave;
+       reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */
+
+       priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
+       priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
+
+       handle_done_ptds(hcd);
 
        irqret = IRQ_HANDLED;
 leave:
@@ -1335,6 +1256,138 @@ leave:
        return irqret;
 }
 
+/*
+ * Workaround for problem described in chip errata 2:
+ *
+ * Sometimes interrupts are not generated when ATL (not INT?) completion occurs.
+ * One solution suggested in the errata is to use SOF interrupts _instead_of_
+ * ATL done interrupts (the "instead of" might be important since it seems
+ * enabling ATL interrupts also causes the chip to sometimes - rarely - "forget"
+ * to set the PTD's done bit in addition to not generating an interrupt!).
+ *
+ * So if we use SOF + ATL interrupts, we sometimes get stale PTDs since their
+ * done bit is not being set. This is bad - it blocks the endpoint until reboot.
+ *
+ * If we use SOF interrupts only, we get latency between ptd completion and the
+ * actual handling. This is very noticeable in testusb runs which takes several
+ * minutes longer without ATL interrupts.
+ *
+ * A better solution is to run the code below every SLOT_CHECK_PERIOD ms. If it
+ * finds active ATL slots which are older than SLOT_TIMEOUT ms, it checks the
+ * slot's ACTIVE and VALID bits. If these are not set, the ptd is considered
+ * completed and its done map bit is set.
+ *
+ * The values of SLOT_TIMEOUT and SLOT_CHECK_PERIOD have been arbitrarily chosen
+ * not to cause too much lag when this HW bug occurs, while still hopefully
+ * ensuring that the check does not falsely trigger.
+ */
+#define SLOT_TIMEOUT 300
+#define SLOT_CHECK_PERIOD 200
+static struct timer_list errata2_timer;
+
+void errata2_function(unsigned long data)
+{
+       struct usb_hcd *hcd = (struct usb_hcd *) data;
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       int slot;
+       struct ptd ptd;
+       unsigned long spinflags;
+
+       spin_lock_irqsave(&priv->lock, spinflags);
+
+       for (slot = 0; slot < 32; slot++)
+               if (priv->atl_slots[slot].qh && time_after(jiffies,
+                                       priv->atl_slots[slot].timestamp +
+                                       SLOT_TIMEOUT * HZ / 1000)) {
+                       ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+                       if (!FROM_DW0_VALID(ptd.dw0) &&
+                                       !FROM_DW3_ACTIVE(ptd.dw3))
+                               priv->atl_done_map |= 1 << slot;
+               }
+
+       if (priv->atl_done_map)
+               handle_done_ptds(hcd);
+
+       spin_unlock_irqrestore(&priv->lock, spinflags);
+
+       errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
+       add_timer(&errata2_timer);
+}
+
+static int isp1760_run(struct usb_hcd *hcd)
+{
+       int retval;
+       u32 temp;
+       u32 command;
+       u32 chipid;
+
+       hcd->uses_new_polling = 1;
+
+       hcd->state = HC_STATE_RUNNING;
+
+       /* Set PTD interrupt AND & OR maps */
+       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0);
+       reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff);
+       reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0);
+       reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff);
+       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0);
+       reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff);
+       /* step 23 passed */
+
+       temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+       reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN);
+
+       command = reg_read32(hcd->regs, HC_USBCMD);
+       command &= ~(CMD_LRESET|CMD_RESET);
+       command |= CMD_RUN;
+       reg_write32(hcd->regs, HC_USBCMD, command);
+
+       retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000);
+       if (retval)
+               return retval;
+
+       /*
+        * XXX
+        * Spec says to write FLAG_CF as last config action, priv code grabs
+        * the semaphore while doing so.
+        */
+       down_write(&ehci_cf_port_reset_rwsem);
+       reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF);
+
+       retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000);
+       up_write(&ehci_cf_port_reset_rwsem);
+       if (retval)
+               return retval;
+
+       init_timer(&errata2_timer);
+       errata2_timer.function = errata2_function;
+       errata2_timer.data = (unsigned long) hcd;
+       errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
+       add_timer(&errata2_timer);
+
+       chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+       dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
+                                       chipid & 0xffff, chipid >> 16);
+
+       /* PTD Register Init Part 2, Step 28 */
+
+       /* Setup registers controlling PTD checking */
+       reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000);
+       reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000);
+       reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001);
+       reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff);
+       reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff);
+       reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff);
+       reg_write32(hcd->regs, HC_BUFFER_STATUS_REG,
+                                               ATL_BUF_FILL | INT_BUF_FILL);
+
+       /* GRR this is run-once init(), being done every time the HC starts.
+        * So long as they're part of class devices, we can't do it init()
+        * since the class device isn't created that early.
+        */
+       return 0;
+}
+
 static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len)
 {
        qtd->data_buffer = databuffer;
@@ -1503,7 +1556,6 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
        packetize_urb(hcd, urb, &new_qtds, mem_flags);
        if (list_empty(&new_qtds))
                return -ENOMEM;
-       urb->hcpriv = NULL; /* Used to signal unlink to interrupt handler */
 
        retval = 0;
        spin_lock_irqsave(&priv->lock, spinflags);
@@ -1531,6 +1583,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
                qh = qh_alloc(GFP_ATOMIC);
                if (!qh) {
                        retval = -ENOMEM;
+                       usb_hcd_unlink_urb_from_ep(hcd, urb);
                        goto out;
                }
                list_add_tail(&qh->qh_list, ep_queue);
@@ -1570,7 +1623,41 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb,
        }
 
        qh->slot = -1;
-       priv->active_ptds--;
+}
+
+/*
+ * Retire the qtds beginning at 'qtd' and belonging all to the same urb, killing
+ * any active transfer belonging to the urb in the process.
+ */
+static void dequeue_urb_from_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh,
+                                               struct isp1760_qtd *qtd)
+{
+       struct urb *urb;
+       int urb_was_running;
+
+       urb = qtd->urb;
+       urb_was_running = 0;
+       list_for_each_entry_from(qtd, &qh->qtd_list, qtd_list) {
+               if (qtd->urb != urb)
+                       break;
+
+               if (qtd->status >= QTD_XFER_STARTED)
+                       urb_was_running = 1;
+               if (last_qtd_of_urb(qtd, qh) &&
+                                       (qtd->status >= QTD_XFER_COMPLETE))
+                       urb_was_running = 0;
+
+               if (qtd->status == QTD_XFER_STARTED)
+                       kill_transfer(hcd, urb, qh);
+               qtd->status = QTD_RETIRE;
+       }
+
+       if ((urb->dev->speed != USB_SPEED_HIGH) && urb_was_running) {
+               qh->tt_buffer_dirty = 1;
+               if (usb_hub_clear_tt_buffer(urb))
+                       /* Clear failed; let's hope things work anyway */
+                       qh->tt_buffer_dirty = 0;
+       }
 }
 
 static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
@@ -1595,9 +1682,8 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
        list_for_each_entry(qtd, &qh->qtd_list, qtd_list)
                if (qtd->urb == urb) {
-                       if (qtd->status == QTD_XFER_STARTED)
-                               kill_transfer(hcd, urb, qh);
-                       qtd->status = QTD_RETIRE;
+                       dequeue_urb_from_qtd(hcd, qh, qtd);
+                       break;
                }
 
        urb->status = status;
@@ -1622,12 +1708,11 @@ static void isp1760_endpoint_disable(struct usb_hcd *hcd,
        if (!qh)
                goto out;
 
-       list_for_each_entry(qtd, &qh->qtd_list, qtd_list) {
-               if (qtd->status == QTD_XFER_STARTED)
-                       kill_transfer(hcd, qtd->urb, qh);
-               qtd->status = QTD_RETIRE;
-               qtd->urb->status = -ECONNRESET;
-       }
+       list_for_each_entry(qtd, &qh->qtd_list, qtd_list)
+               if (qtd->status != QTD_RETIRE) {
+                       dequeue_urb_from_qtd(hcd, qh, qtd);
+                       qtd->urb->status = -ECONNRESET;
+               }
 
        ep->hcpriv = NULL;
        /* Cannot free qh here since it will be parsed by schedule_ptds() */
@@ -2021,6 +2106,8 @@ static void isp1760_stop(struct usb_hcd *hcd)
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
        u32 temp;
 
+       del_timer(&errata2_timer);
+
        isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
                        NULL, 0);
        mdelay(20);
@@ -2048,6 +2135,23 @@ static void isp1760_shutdown(struct usb_hcd *hcd)
        reg_write32(hcd->regs, HC_USBCMD, command);
 }
 
+static void isp1760_clear_tt_buffer_complete(struct usb_hcd *hcd,
+                                               struct usb_host_endpoint *ep)
+{
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       struct isp1760_qh *qh = ep->hcpriv;
+       unsigned long spinflags;
+
+       if (!qh)
+               return;
+
+       spin_lock_irqsave(&priv->lock, spinflags);
+       qh->tt_buffer_dirty = 0;
+       schedule_ptds(hcd);
+       spin_unlock_irqrestore(&priv->lock, spinflags);
+}
+
+
 static const struct hc_driver isp1760_hc_driver = {
        .description            = "isp1760-hcd",
        .product_desc           = "NXP ISP1760 USB Host Controller",
@@ -2064,6 +2168,7 @@ static const struct hc_driver isp1760_hc_driver = {
        .get_frame_number       = isp1760_get_frame,
        .hub_status_data        = isp1760_hub_status_data,
        .hub_control            = isp1760_hub_control,
+       .clear_tt_buffer_complete       = isp1760_clear_tt_buffer_complete,
 };
 
 int __init init_kmem_once(void)