upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / drivers / usb / host / ehci-q.c
index 69107cc..7df9b9a 100644 (file)
@@ -198,9 +198,9 @@ static void qtd_copy_status (
                                && urb->dev->tt && !usb_pipeint (urb->pipe)
                                && ((token & QTD_STS_MMF) != 0
                                        || QTD_CERR(token) == 0)
-                               && (!ehci_is_ARC(ehci)
+                               && (!ehci_is_TDI(ehci)
                                        || urb->dev->tt->hub !=
-                                               ehci->hcd.self.root_hub)) {
+                                          ehci_to_hcd(ehci)->self.root_hub)) {
 #ifdef DEBUG
                        struct usb_device *tt = urb->dev->tt->hub;
                        dev_dbg (&tt->dev,
@@ -218,14 +218,14 @@ ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs)
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
-       if (likely (urb->hcpriv != 0)) {
+       if (likely (urb->hcpriv != NULL)) {
                struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
 
                /* S-mask in a QH means it's an interrupt urb */
                if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
 
                        /* ... update hc-wide periodic stats (for usbfs) */
-                       hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--;
+                       ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
                }
                qh_put (qh);
        }
@@ -262,14 +262,14 @@ __acquires(ehci->lock)
 
        /* complete() can reenter this HCD */
        spin_unlock (&ehci->lock);
-       usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
+       usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb, regs);
        spin_lock (&ehci->lock);
 }
 
 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, int wait);
+static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
 
 /*
@@ -338,23 +338,24 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
                        if ((token & QTD_STS_HALT) != 0) {
                                stopped = 1;
 
-                       /* magic dummy for some short reads; qh won't advance */
+                       /* magic dummy for some short reads; qh won't advance.
+                        * that silicon quirk can kick in with this dummy too.
+                        */
                        } else if (IS_SHORT_READ (token)
-                                       && (qh->hw_alt_next & QTD_MASK)
-                                               == ehci->async->hw_alt_next) {
+                                       && !(qtd->hw_alt_next & EHCI_LIST_END)) {
                                stopped = 1;
                                goto halt;
                        }
 
                /* stop scanning when we reach qtds the hc is using */
                } else if (likely (!stopped
-                               && HCD_IS_RUNNING (ehci->hcd.state))) {
+                               && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
                        break;
 
                } else {
                        stopped = 1;
 
-                       if (unlikely (!HCD_IS_RUNNING (ehci->hcd.state)))
+                       if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
                                urb->status = -ESHUTDOWN;
 
                        /* ignore active urbs unless some previous qtd
@@ -405,7 +406,7 @@ halt:
        }
 
        /* last urb's completion might still need calling */
-       if (likely (last != 0)) {
+       if (likely (last != NULL)) {
                ehci_urb_done (ehci, last->urb, regs);
                count++;
                ehci_qtd_free (ehci, last);
@@ -428,10 +429,10 @@ halt:
                         * except maybe high bandwidth ...
                         */
                        if (qh->period) {
-                               intr_deschedule (ehci, qh, 1);
+                               intr_deschedule (ehci, qh);
                                (void) qh_schedule (ehci, qh);
                        } else
-                               start_unlink_async (ehci, qh);
+                               unlink_async (ehci, qh);
                        break;
                /* otherwise, unlink already started */
                }
@@ -522,7 +523,7 @@ qh_urb_transaction (
        else
                buf = 0;
 
-       // FIXME this 'buf' check break some zlps...
+       /* for zero length DATA stages, STATUS is always IN */
        if (!buf || is_input)
                token |= (1 /* "in" */ << 8);
        /* else it's already initted to "out" pid (0 << 8) */
@@ -664,9 +665,12 @@ qh_make (
                        qh->c_usecs = 0;
                        qh->gap_uf = 0;
 
-                       /* FIXME handle HS periods of less than 1 frame. */
                        qh->period = urb->interval >> 3;
-                       if (qh->period < 1) {
+                       if (qh->period == 0 && urb->interval != 1) {
+                               /* NOTE interval 2 or 4 uframes could work.
+                                * But interval 1 scheduling is simpler, and
+                                * includes high bandwidth.
+                                */
                                dbg ("intr period %d uframes, NYET!",
                                                urb->interval);
                                goto done;
@@ -711,11 +715,12 @@ qh_make (
                info2 |= (EHCI_TUNE_MULT_TT << 30);
                info2 |= urb->dev->ttport << 23;
 
-               /* set the address of the TT; for ARC's integrated
+               /* set the address of the TT; for TDI's integrated
                 * root hub tt, leave it zeroed.
                 */
-               if (!ehci_is_ARC(ehci)
-                               || urb->dev->tt->hub != ehci->hcd.self.root_hub)
+               if (!ehci_is_TDI(ehci)
+                               || urb->dev->tt->hub !=
+                                       ehci_to_hcd(ehci)->self.root_hub)
                        info2 |= urb->dev->tt->hub->devnum << 16;
 
                /* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
@@ -776,7 +781,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        (void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
                        cmd |= CMD_ASE | CMD_RUN;
                        writel (cmd, &ehci->regs->command);
-                       ehci->hcd.state = USB_STATE_RUNNING;
+                       ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
                        /* posted write need not be known to HC yet ... */
                }
        }
@@ -832,26 +837,8 @@ static struct ehci_qh *qh_append_tds (
                        qtd = list_entry (qtd_list->next, struct ehci_qtd,
                                        qtd_list);
 
-               /* control qh may need patching after enumeration */
+               /* control qh may need patching ... */
                if (unlikely (epnum == 0)) {
-                       /* set_address changes the address */
-                       if ((qh->hw_info1 & QH_ADDR_MASK) == 0)
-                               qh->hw_info1 |= cpu_to_le32 (
-                                               usb_pipedevice (urb->pipe));
-
-                       /* for full speed, ep0 maxpacket can grow */
-                       else if (!(qh->hw_info1
-                                       & __constant_cpu_to_le32 (0x3 << 12))) {
-                               u32     info, max;
-
-                               info = le32_to_cpu (qh->hw_info1);
-                               max = urb->dev->descriptor.bMaxPacketSize0;
-                               if (max > (0x07ff & (info >> 16))) {
-                                       info &= ~(0x07ff << 16);
-                                       info |= max << 16;
-                                       qh->hw_info1 = cpu_to_le32 (info);
-                               }
-                       }
 
                         /* usb_reset_device() briefly reverts to address 0 */
                         if (usb_pipedevice (urb->pipe) == 0)
@@ -861,7 +848,7 @@ static struct ehci_qh *qh_append_tds (
                /* just one way to queue requests: swap with the dummy qtd.
                 * only hc or qh_refresh() ever modify the overlay.
                 */
-               if (likely (qtd != 0)) {
+               if (likely (qtd != NULL)) {
                        struct ehci_qtd         *dummy;
                        dma_addr_t              dma;
                        __le32                  token;
@@ -908,43 +895,40 @@ static struct ehci_qh *qh_append_tds (
 static int
 submit_async (
        struct ehci_hcd         *ehci,
+       struct usb_host_endpoint *ep,
        struct urb              *urb,
        struct list_head        *qtd_list,
        int                     mem_flags
 ) {
        struct ehci_qtd         *qtd;
-       struct hcd_dev          *dev;
        int                     epnum;
        unsigned long           flags;
        struct ehci_qh          *qh = NULL;
 
        qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
-       dev = (struct hcd_dev *)urb->dev->hcpriv;
-       epnum = usb_pipeendpoint (urb->pipe);
-       if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe))
-               epnum |= 0x10;
+       epnum = ep->desc.bEndpointAddress;
 
 #ifdef EHCI_URB_TRACE
        ehci_dbg (ehci,
                "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
                __FUNCTION__, urb->dev->devpath, urb,
-               epnum & 0x0f, usb_pipein (urb->pipe) ? "in" : "out",
+               epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
                urb->transfer_buffer_length,
-               qtd, dev ? dev->ep [epnum] : (void *)~0);
+               qtd, ep->hcpriv);
 #endif
 
        spin_lock_irqsave (&ehci->lock, flags);
-       qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
+       qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
 
        /* Control/bulk operations through TTs don't need scheduling,
         * the HC and TT handle it when the TT has a buffer ready.
         */
-       if (likely (qh != 0)) {
+       if (likely (qh != NULL)) {
                if (likely (qh->qh_state == QH_STATE_IDLE))
                        qh_link_async (ehci, qh_get (qh));
        }
        spin_unlock_irqrestore (&ehci->lock, flags);
-       if (unlikely (qh == 0)) {
+       if (unlikely (qh == NULL)) {
                qtd_list_free (ehci, urb, qtd_list);
                return -ENOMEM;
        }
@@ -976,7 +960,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
        qh_completions (ehci, qh, regs);
 
        if (!list_empty (&qh->qtd_list)
-                       && HCD_IS_RUNNING (ehci->hcd.state))
+                       && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
                qh_link_async (ehci, qh);
        else {
                qh_put (qh);            // refcount from async list
@@ -984,8 +968,8 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
                /* it's not free to turn the async schedule on/off; leave it
                 * active but idle for a while once it empties.
                 */
-               if (HCD_IS_RUNNING (ehci->hcd.state)
-                               && ehci->async->qh_next.qh == 0)
+               if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
+                               && ehci->async->qh_next.qh == NULL)
                        timer_action (ehci, TIMER_ASYNC_OFF);
        }
 
@@ -1004,13 +988,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        struct ehci_qh  *prev;
 
 #ifdef DEBUG
+       assert_spin_locked(&ehci->lock);
        if (ehci->reclaim
                        || (qh->qh_state != QH_STATE_LINKED
                                && qh->qh_state != QH_STATE_UNLINK_WAIT)
-#ifdef CONFIG_SMP
-// this macro lies except on SMP compiles
-                       || !spin_is_locked (&ehci->lock)
-#endif
                        )
                BUG ();
 #endif
@@ -1018,7 +999,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        /* stop async schedule right now? */
        if (unlikely (qh == ehci->async)) {
                /* can't get here without STS_ASS set */
-               if (ehci->hcd.state != USB_STATE_HALT) {
+               if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) {
                        writel (cmd & ~CMD_ASE, &ehci->regs->command);
                        wmb ();
                        // handshake later, if we need to
@@ -1038,7 +1019,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        prev->qh_next = qh->qh_next;
        wmb ();
 
-       if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
+       if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
                /* if (unlikely (qh->reclaim != 0))
                 *      this will recurse, probably not much
                 */
@@ -1066,7 +1047,7 @@ scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
        timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
        qh = ehci->async->qh_next.qh;
-       if (likely (qh != 0)) {
+       if (likely (qh != NULL)) {
                do {
                        /* clean any finished work for this qh */
                        if (!list_empty (&qh->qtd_list)