This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / usb / host / uhci-hcd.c
index 614403b..20a42f9 100644 (file)
@@ -51,8 +51,8 @@
 #include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb.h>
-#include <linux/bitops.h>
 
+#include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -92,7 +92,7 @@ static char *errbuf;
 
 static kmem_cache_t *uhci_up_cachep;   /* urb_priv */
 
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci);
+static int uhci_get_current_frame_number(struct uhci_hcd *uhci);
 static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
 static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
 static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
@@ -174,7 +174,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
  */
 static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
 {
-       framenum &= (UHCI_NUMFRAMES - 1);
+       framenum %= UHCI_NUMFRAMES;
 
        td->frame = framenum;
 
@@ -230,22 +230,42 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
 }
 
 /*
- * Inserts a td list into qh.
+ * Inserts a td into qh list at the top.
  */
 static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
 {
+       struct list_head *tmp, *head;
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       struct uhci_td *td;
-       u32 *plink;
+       struct uhci_td *td, *ptd;
+
+       if (list_empty(&urbp->td_list))
+               return;
+
+       head = &urbp->td_list;
+       tmp = head->next;
 
        /* Ordering isn't important here yet since the QH hasn't been */
-       /* inserted into the schedule yet */
-       plink = &qh->element;
-       list_for_each_entry(td, &urbp->td_list, list) {
-               *plink = cpu_to_le32(td->dma_handle) | breadth;
-               plink = &td->link;
+       /*  inserted into the schedule yet */
+       td = list_entry(tmp, struct uhci_td, list);
+
+       /* Add the first TD to the QH element pointer */
+       qh->element = cpu_to_le32(td->dma_handle) | breadth;
+
+       ptd = td;
+
+       /* Then link the rest of the TD's */
+       tmp = tmp->next;
+       while (tmp != head) {
+               td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
+
+               ptd->link = cpu_to_le32(td->dma_handle) | breadth;
+
+               ptd = td;
        }
-       *plink = UHCI_PTR_TERM;
+
+       ptd->link = UHCI_PTR_TERM;
 }
 
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
@@ -310,7 +330,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
 {
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       struct urb_priv *turbp;
+       struct list_head *tmp;
        struct uhci_qh *lqh;
 
        /* Grab the last QH */
@@ -338,8 +358,12 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct
         */
        lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
        if (lqh->urbp) {
-               list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
+               list_for_each (tmp, &lqh->urbp->queue_list) {
+                       struct urb_priv *turbp =
+                               list_entry(tmp, struct urb_priv, queue_list);
+
                        turbp->qh->link = lqh->link;
+               }
        }
 
        list_add_tail(&urbp->qh->list, &skelqh->list);
@@ -381,11 +405,18 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
                pqh = list_entry(qh->list.prev, struct uhci_qh, list);
                pqh->link = newlink;
                if (pqh->urbp) {
-                       struct urb_priv *turbp;
+                       struct list_head *head, *tmp;
+
+                       head = &pqh->urbp->queue_list;
+                       tmp = head->next;
+                       while (head != tmp) {
+                               struct urb_priv *turbp =
+                                       list_entry(tmp, struct urb_priv, queue_list);
+
+                               tmp = tmp->next;
 
-                       list_for_each_entry(turbp, &pqh->urbp->queue_list,
-                                       queue_list)
                                turbp->qh->link = newlink;
+                       }
                }
                wmb();
 
@@ -416,14 +447,21 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
 {
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       struct uhci_td *td;
+       struct list_head *head, *tmp;
+
+       head = &urbp->td_list;
+       tmp = head->next;
+       while (head != tmp) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
 
-       list_for_each_entry(td, &urbp->td_list, list) {
                if (toggle)
                        td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
                else
                        td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
 
+
                toggle ^= 1;
        }
 
@@ -435,19 +473,30 @@ static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
 static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
 {
        struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
+       struct list_head *tmp;
        struct uhci_td *lltd;
 
        eurbp = eurb->hcpriv;
        urbp = urb->hcpriv;
 
        /* Find the first URB in the queue */
-       furbp = eurbp;
        if (eurbp->queued) {
-               list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
-                       if (!furbp->queued)
+               struct list_head *head = &eurbp->queue_list;
+
+               tmp = head->next;
+               while (tmp != head) {
+                       struct urb_priv *turbp =
+                               list_entry(tmp, struct urb_priv, queue_list);
+
+                       if (!turbp->queued)
                                break;
-       }
 
+                       tmp = tmp->next;
+               }
+       } else
+               tmp = &eurbp->queue_list;
+
+       furbp = list_entry(tmp, struct urb_priv, queue_list);
        lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
 
        lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
@@ -473,7 +522,9 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
 
 static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
 {
-       struct urb_priv *urbp, *nurbp, *purbp, *turbp;
+       struct urb_priv *urbp, *nurbp;
+       struct list_head *head, *tmp;
+       struct urb_priv *purbp;
        struct uhci_td *pltd;
        unsigned int toggle;
 
@@ -505,7 +556,14 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
                        toggle = uhci_toggle(td_token(pltd)) ^ 1;
                }
 
-               list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
+               head = &urbp->queue_list;
+               tmp = head->next;
+               while (head != tmp) {
+                       struct urb_priv *turbp;
+
+                       turbp = list_entry(tmp, struct urb_priv, queue_list);
+                       tmp = tmp->next;
+
                        if (!turbp->queued)
                                break;
                        toggle = uhci_fixup_toggle(turbp->urb, toggle);
@@ -579,7 +637,7 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
 
 static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
 {
-       struct uhci_td *td, *tmp;
+       struct list_head *head, *tmp;
        struct urb_priv *urbp;
        unsigned int age;
 
@@ -602,7 +660,13 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
        if (list_empty(&uhci->td_remove_list))
                uhci_set_next_interrupt(uhci);
 
-       list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+       head = &urbp->td_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
+
                uhci_remove_td_from_urb(td);
                uhci_remove_td(uhci, td);
                list_add(&td->remove_list, &uhci->td_remove_list);
@@ -765,12 +829,8 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
 
        uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
 
-       /* Low-speed transfers get a different queue, and won't hog the bus.
-        * Also, some devices enumerate better without FSBR; the easiest way
-        * to do that is to put URBs on the low-speed queue while the device
-        * is in the DEFAULT state. */
-       if (urb->dev->speed == USB_SPEED_LOW ||
-                       urb->dev->state == USB_STATE_DEFAULT)
+       /* Low-speed transfers get a different queue, and won't hog the bus */
+       if (urb->dev->speed == USB_SPEED_LOW)
                skelqh = uhci->skel_ls_control_qh;
        else {
                skelqh = uhci->skel_fs_control_qh;
@@ -1023,6 +1083,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
  */
 static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 {
+       struct list_head *tmp, *head;
        struct urb_priv *urbp = urb->hcpriv;
        struct uhci_td *td;
        unsigned int status = 0;
@@ -1030,7 +1091,13 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 
        urb->actual_length = 0;
 
-       list_for_each_entry(td, &urbp->td_list, list) {
+       head = &urbp->td_list;
+       tmp = head->next;
+       while (tmp != head) {
+               td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
+
                status = uhci_status_bits(td_status(td));
                if (status & TD_CTRL_ACTIVE)
                        return -EINPROGRESS;
@@ -1109,12 +1176,17 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
 static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
 {
        struct urb *last_urb = NULL;
-       struct urb_priv *up;
+       struct list_head *tmp, *head;
        int ret = 0;
 
-       list_for_each_entry(up, &uhci->urb_list, urb_list) {
+       head = &uhci->urb_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list);
                struct urb *u = up->urb;
 
+               tmp = tmp->next;
+
                /* look for pending URB's with identical pipe handle */
                if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
                    (u->status == -EINPROGRESS) && (u != urb)) {
@@ -1145,14 +1217,15 @@ static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
        limits = isochronous_find_limits(uhci, urb, &start, &end);
 
        if (urb->transfer_flags & URB_ISO_ASAP) {
-               if (limits)
-                       urb->start_frame =
-                                       (uhci_get_current_frame_number(uhci) +
-                                               10) & (UHCI_NUMFRAMES - 1);
-               else
+               if (limits) {
+                       int curframe;
+
+                       curframe = uhci_get_current_frame_number(uhci) % UHCI_NUMFRAMES;
+                       urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES;
+               } else
                        urb->start_frame = end;
        } else {
-               urb->start_frame &= (UHCI_NUMFRAMES - 1);
+               urb->start_frame %= UHCI_NUMFRAMES;
                /* FIXME: Sanity check */
        }
 
@@ -1199,7 +1272,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
 static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 {
-       struct uhci_td *td;
+       struct list_head *tmp, *head;
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
        int status;
        int i, ret = 0;
@@ -1207,9 +1280,14 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
        urb->actual_length = 0;
 
        i = 0;
-       list_for_each_entry(td, &urbp->td_list, list) {
+       head = &urbp->td_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
                int actlength;
 
+               tmp = tmp->next;
+
                if (td_status(td) & TD_CTRL_ACTIVE)
                        return -EINPROGRESS;
 
@@ -1233,15 +1311,20 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
 static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
 {
-       struct urb_priv *up;
+       struct list_head *tmp, *head;
 
        /* We don't match Isoc transfers since they are special */
        if (usb_pipeisoc(urb->pipe))
                return NULL;
 
-       list_for_each_entry(up, &uhci->urb_list, urb_list) {
+       head = &uhci->urb_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list);
                struct urb *u = up->urb;
 
+               tmp = tmp->next;
+
                if (u->dev == urb->dev && u->status == -EINPROGRESS) {
                        /* For control, ignore the direction */
                        if (usb_pipecontrol(urb->pipe) &&
@@ -1392,10 +1475,9 @@ out:
 
 static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
 {
-       struct list_head *head;
-       struct uhci_td *td;
+       struct list_head *head, *tmp;
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       int prevactive = 0;
+       int prevactive = 1;
 
        uhci_dec_fsbr(uhci, urb);       /* Safe since it checks */
 
@@ -1403,28 +1485,25 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
         * Now we need to find out what the last successful toggle was
         * so we can update the local data toggle for the next transfer
         *
-        * There are 2 ways the last successful completed TD is found:
+        * There's 3 way's the last successful completed TD is found:
         *
         * 1) The TD is NOT active and the actual length < expected length
         * 2) The TD is NOT active and it's the last TD in the chain
-        *
-        * and a third way the first uncompleted TD is found:
-        *
         * 3) The TD is active and the previous TD is NOT active
         *
         * Control and Isochronous ignore the toggle, so this is safe
         * for all types
-        *
-        * FIXME: The toggle fixups won't be 100% reliable until we
-        * change over to using a single queue for each endpoint and
-        * stop the queue before unlinking.
         */
        head = &urbp->td_list;
-       list_for_each_entry(td, head, list) {
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
+
                if (!(td_status(td) & TD_CTRL_ACTIVE) &&
-                               (uhci_actual_length(td_status(td)) <
-                                uhci_expected_length(td_token(td)) ||
-                               td->list.next == head))
+                   (uhci_actual_length(td_status(td)) < uhci_expected_length(td_token(td)) ||
+                   tmp == head))
                        usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
                                uhci_packetout(td_token(td)),
                                uhci_toggle(td_token(td)) ^ 1);
@@ -1477,8 +1556,7 @@ done:
 static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
 {
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       struct list_head *head;
-       struct uhci_td *td;
+       struct list_head *head, *tmp;
        int count = 0;
 
        uhci_dec_fsbr(uhci, urb);
@@ -1492,14 +1570,18 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
         */
 
        head = &urbp->td_list;
-       list_for_each_entry(td, head, list) {
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+               tmp = tmp->next;
+
                /*
                 * Make sure we don't do the last one (since it'll have the
                 * TERM bit set) as well as we skip every so many TD's to
                 * make sure it doesn't hog the bandwidth
                 */
-               if (td->list.next != head && (count % DEPTH_INTERVAL) ==
-                               (DEPTH_INTERVAL - 1))
+               if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1))
                        td->link |= UHCI_PTR_DEPTH;
 
                count++;
@@ -1513,7 +1595,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
  *
  * returns the current frame number for a USB bus/controller.
  */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
+static int uhci_get_current_frame_number(struct uhci_hcd *uhci)
 {
        return inw(uhci->io_addr + USBFRNUM);
 }
@@ -1524,10 +1606,12 @@ static void stall_callback(unsigned long ptr)
 {
        struct usb_hcd *hcd = (struct usb_hcd *)ptr;
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       struct urb_priv *up;
+       struct list_head list, *tmp, *head;
        unsigned long flags;
        int called_uhci_finish_completion = 0;
 
+       INIT_LIST_HEAD(&list);
+
        spin_lock_irqsave(&uhci->schedule_lock, flags);
        if (!list_empty(&uhci->urb_remove_list) &&
            uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
@@ -1536,9 +1620,14 @@ static void stall_callback(unsigned long ptr)
                called_uhci_finish_completion = 1;
        }
 
-       list_for_each_entry(up, &uhci->urb_list, urb_list) {
+       head = &uhci->urb_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list);
                struct urb *u = up->urb;
 
+               tmp = tmp->next;
+
                spin_lock(&u->lock);
 
                /* Check if the FSBR timed out */
@@ -1553,6 +1642,17 @@ static void stall_callback(unsigned long ptr)
        if (called_uhci_finish_completion)
                wake_up_all(&uhci->waitqh);
 
+       head = &list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list);
+               struct urb *u = up->urb;
+
+               tmp = tmp->next;
+
+               uhci_urb_dequeue(hcd, u);
+       }
+
        /* Really disable FSBR */
        if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
                uhci->fsbrtimeout = 0;
@@ -1561,8 +1661,6 @@ static void stall_callback(unsigned long ptr)
 
        /* Poll for and perform state transitions */
        hc_state_transitions(uhci);
-       if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
-               uhci_check_resume(uhci);
 
        init_stall_timer(hcd);
 }
@@ -1582,9 +1680,15 @@ static int init_stall_timer(struct usb_hcd *hcd)
 
 static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
 {
-       struct uhci_qh *qh, *tmp;
+       struct list_head *tmp, *head;
+
+       head = &uhci->qh_remove_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list);
+
+               tmp = tmp->next;
 
-       list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
                list_del_init(&qh->remove_list);
 
                uhci_free_qh(uhci, qh);
@@ -1593,19 +1697,22 @@ static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
 
 static void uhci_free_pending_tds(struct uhci_hcd *uhci)
 {
-       struct uhci_td *td, *tmp;
+       struct list_head *tmp, *head;
+
+       head = &uhci->td_remove_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, remove_list);
+
+               tmp = tmp->next;
 
-       list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
                list_del_init(&td->remove_list);
 
                uhci_free_td(uhci, td);
        }
 }
 
-static void
-uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
-__releases(uhci->schedule_lock)
-__acquires(uhci->schedule_lock)
+static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
@@ -1619,13 +1726,19 @@ __acquires(uhci->schedule_lock)
 static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       struct urb_priv *urbp, *tmp;
+       struct list_head *tmp, *head;
 
-       list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
+       head = &uhci->complete_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
                struct urb *urb = urbp->urb;
 
                list_del_init(&urbp->urb_list);
                uhci_finish_urb(hcd, urb, regs);
+
+               head = &uhci->complete_list;
+               tmp = head->next;
        }
 }
 
@@ -1641,7 +1754,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        unsigned long io_addr = uhci->io_addr;
        unsigned short status;
-       struct urb_priv *urbp, *tmp;
+       struct list_head *tmp, *head;
        unsigned int age;
 
        /*
@@ -1688,11 +1801,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
        else
                uhci_set_next_interrupt(uhci);
 
-       /* Walk the list of pending URBs to see which ones completed
-        * (must be _safe because uhci_transfer_result() dequeues URBs) */
-       list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
+       /* Walk the list of pending URB's to see which ones completed */
+       head = &uhci->urb_list;
+       tmp = head->next;
+       while (tmp != head) {
+               struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
                struct urb *urb = urbp->urb;
 
+               tmp = tmp->next;
+
                /* Checks the status and does all of the magic necessary */
                uhci_transfer_result(uhci, urb);
        }
@@ -1854,10 +1971,10 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
        }
 }
 
-static int start_hc(struct uhci_hcd *uhci)
+static void start_hc(struct uhci_hcd *uhci)
 {
        unsigned long io_addr = uhci->io_addr;
-       int timeout = 10;
+       int timeout = 1000;
 
        /*
         * Reset the HC - this will force us to get a
@@ -1867,11 +1984,10 @@ static int start_hc(struct uhci_hcd *uhci)
         */
        outw(USBCMD_HCRESET, io_addr + USBCMD);
        while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
-               if (--timeout < 0) {
+               if (!--timeout) {
                        dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
-                       return -ETIMEDOUT;
+                       break;
                }
-               msleep(1);
        }
 
        /* Turn on PIRQ and all interrupts */
@@ -1890,7 +2006,6 @@ static int start_hc(struct uhci_hcd *uhci)
        outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
 
         uhci->hcd.state = USB_STATE_RUNNING;
-       return 0;
 }
 
 /*
@@ -2142,8 +2257,7 @@ static int uhci_start(struct usb_hcd *hcd)
         * the memory writes above before the I/O transfers in start_hc().
         */
        mb();
-       if ((retval = start_hc(uhci)) != 0)
-               goto err_alloc_skelqh;
+       start_hc(uhci);
 
        init_stall_timer(hcd);
 
@@ -2249,7 +2363,6 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
 static int uhci_resume(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       int rc;
 
        pci_set_master(to_pci_dev(uhci_dev(uhci)));
 
@@ -2272,8 +2385,7 @@ static int uhci_resume(struct usb_hcd *hcd)
                                USBLEGSUP_DEFAULT);
        } else {
                reset_hc(uhci);
-               if ((rc = start_hc(uhci)) != 0)
-                       return rc;
+               start_hc(uhci);
        }
        uhci->hcd.state = USB_STATE_RUNNING;
        return 0;
@@ -2293,6 +2405,11 @@ static struct usb_hcd *uhci_hcd_alloc(void)
        return &uhci->hcd;
 }
 
+static void uhci_hcd_free(struct usb_hcd *hcd)
+{
+       kfree(hcd_to_uhci(hcd));
+}
+
 /* Are there any URBs for a particular device/endpoint on a given list? */
 static int urbs_for_ep_list(struct list_head *head,
                struct hcd_dev *hdev, int ep)
@@ -2357,6 +2474,7 @@ static const struct hc_driver uhci_driver = {
        .stop =                 uhci_stop,
 
        .hcd_alloc =            uhci_hcd_alloc,
+       .hcd_free =             uhci_hcd_free,
 
        .urb_enqueue =          uhci_urb_enqueue,
        .urb_dequeue =          uhci_urb_dequeue,
@@ -2416,7 +2534,7 @@ static int __init uhci_hcd_init(void)
        if (!uhci_up_cachep)
                goto up_failed;
 
-       retval = pci_register_driver(&uhci_pci_driver);
+       retval = pci_module_init(&uhci_pci_driver);
        if (retval)
                goto init_failed;