}
 }
 
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
+               struct uhci_td *td)
 {
        /* If it's not inserted, don't remove it */
-       if (td->frame == -1 && list_empty(&td->fl_list))
+       if (td->frame == -1) {
+               WARN_ON(!list_empty(&td->fl_list));
                return;
+       }
 
-       if (td->frame != -1 && uhci->frame_cpu[td->frame] == td) {
+       if (uhci->frame_cpu[td->frame] == td) {
                if (list_empty(&td->fl_list)) {
                        uhci->frame[td->frame] = td->link;
                        uhci->frame_cpu[td->frame] = NULL;
                ptd->link = td->link;
        }
 
-       wmb();
-       td->link = UHCI_PTR_TERM;
-
        list_del_init(&td->fl_list);
        td->frame = -1;
 }
 
+static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+{
+       struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+       struct uhci_td *td;
+
+       list_for_each_entry(td, &urbp->td_list, list)
+               uhci_remove_td_frame_list(uhci, td);
+       wmb();
+}
+
 /*
  * Inserts a td list into qh.
  */
 
        list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
                uhci_remove_td_from_urb(td);
-               uhci_remove_td(uhci, td);
                list_add(&td->remove_list, &uhci->td_remove_list);
        }
 
        struct uhci_td *td;
        int i, ret, frame;
        int status, destination;
+       struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
        status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
        destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
        if (ret)
                return ret;
 
-       frame = urb->start_frame;
-       for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
-               if (!urb->iso_frame_desc[i].length)
-                       continue;
-
+       for (i = 0; i < urb->number_of_packets; i++) {
                td = uhci_alloc_td(uhci);
                if (!td)
                        return -ENOMEM;
 
                if (i + 1 >= urb->number_of_packets)
                        td->status |= cpu_to_le32(TD_CTRL_IOC);
+       }
 
+       frame = urb->start_frame;
+       list_for_each_entry(td, &urbp->td_list, list) {
                uhci_insert_td_frame_list(uhci, td, frame);
+               frame += urb->interval;
        }
 
        return -EINPROGRESS;
        int status;
        int i, ret = 0;
 
-       urb->actual_length = 0;
+       urb->actual_length = urb->error_count = 0;
 
        i = 0;
        list_for_each_entry(td, &urbp->td_list, list) {
 
                i++;
        }
+       unlink_isochronous_tds(uhci, urb);
 
        return ret;
 }
                goto done;
        list_del_init(&urbp->urb_list);
 
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+               unlink_isochronous_tds(uhci, urb);
        uhci_unlink_generic(uhci, urb);
 
        uhci_get_current_frame_number(uhci);