u32 toggle;
        u32 ping;
        int slot;
+       int tt_buffer_dirty;    /* See USB2.0 spec section 11.17.5 */
 };
 
 struct urb_listitem {
                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;
 
                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;
        qh->slot = -1;
 }
 
+/*
+ * 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,
                int status)
 {
 
        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;
        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() */
        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",
        .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)