Merge branch 'intx' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[pandora-kernel.git] / drivers / usb / host / uhci-q.c
index c9d72ac..30b8845 100644 (file)
@@ -372,7 +372,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
                 * need to change any toggles in this URB */
                td = list_entry(urbp->td_list.next, struct uhci_td, list);
                if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
-                       td = list_entry(urbp->td_list.next, struct uhci_td,
+                       td = list_entry(urbp->td_list.prev, struct uhci_td,
                                        list);
                        toggle = uhci_toggle(td_token(td)) ^ 1;
 
@@ -498,7 +498,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
 {
        struct urb_priv *urbp;
 
-       urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+       urbp = kmem_cache_alloc(uhci_up_cachep, GFP_ATOMIC);
        if (!urbp)
                return NULL;
 
@@ -943,7 +943,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
                        /* We received a short packet */
                        if (urb->transfer_flags & URB_SHORT_NOT_OK)
                                ret = -EREMOTEIO;
-                       else if (ctrlstat & TD_CTRL_SPD)
+
+                       /* Fixup needed only if this isn't the URB's last TD */
+                       else if (&td->list != urbp->td_list.prev)
                                ret = 1;
                }
 
@@ -1242,7 +1244,7 @@ done:
  * Finish unlinking an URB and give it back
  */
 static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
-               struct urb *urb, struct pt_regs *regs)
+               struct urb *urb)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
@@ -1291,7 +1293,7 @@ __acquires(uhci->lock)
        }
 
        spin_unlock(&uhci->lock);
-       usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs);
+       usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
        spin_lock(&uhci->lock);
 
        /* If the queue is now empty, we can unlink the QH and give up its
@@ -1311,8 +1313,7 @@ __acquires(uhci->lock)
                (qh->state == QH_STATE_UNLINKING &&     \
                uhci->frame_number + uhci->is_stopped != qh->unlink_frame)
 
-static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
-               struct pt_regs *regs)
+static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
        struct urb_priv *urbp;
        struct urb *urb;
@@ -1345,8 +1346,8 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
                                return;
                }
 
-               uhci_giveback_urb(uhci, qh, urb, regs);
-               if (status < 0)
+               uhci_giveback_urb(uhci, qh, urb);
+               if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
                        break;
        }
 
@@ -1370,7 +1371,7 @@ restart:
                                qh->is_stopped = 0;
                                return;
                        }
-                       uhci_giveback_urb(uhci, qh, urb, regs);
+                       uhci_giveback_urb(uhci, qh, urb);
                        goto restart;
                }
        }
@@ -1485,7 +1486,7 @@ done:
 /*
  * Process events in the schedule, but only in one thread at a time
  */
-static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+static void uhci_scan_schedule(struct uhci_hcd *uhci)
 {
        int i;
        struct uhci_qh *qh;
@@ -1513,7 +1514,7 @@ rescan:
                                        struct uhci_qh, node);
 
                        if (uhci_advance_check(uhci, qh)) {
-                               uhci_scan_qh(uhci, qh, regs);
+                               uhci_scan_qh(uhci, qh);
                                if (qh->state == QH_STATE_ACTIVE) {
                                        uhci_urbp_wants_fsbr(uhci,
        list_entry(qh->queue.next, struct urb_priv, node));