[PATCH] USB UHCI: Minor improvements
authorAlan Stern <stern@rowland.harvard.edu>
Sat, 9 Apr 2005 21:26:00 +0000 (17:26 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 27 Jun 2005 21:43:43 +0000 (14:43 -0700)
This patch makes a few small improvements in the UHCI driver.  Some
code is moved between different source files and a more useful pointer
is passed to a callback routine.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-q.c

index 8b6c87ef486bfdf27668db2c4150f191d4279276..c17bd7ebc021ace92d11413da4e68686e75b8836 100644 (file)
@@ -100,22 +100,15 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
+static inline void restart_timer(struct uhci_hcd *uhci)
+{
+       mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
+}
+
 #include "uhci-hub.c"
 #include "uhci-debug.c"
 #include "uhci-q.c"
 
-static int ports_active(struct uhci_hcd *uhci)
-{
-       unsigned long io_addr = uhci->io_addr;
-       int connection = 0;
-       int i;
-
-       for (i = 0; i < uhci->rh_numports; i++)
-               connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
-
-       return connection;
-}
-
 static int suspend_allowed(struct uhci_hcd *uhci)
 {
        unsigned long io_addr = uhci->io_addr;
@@ -270,14 +263,14 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
                case UHCI_RUNNING:
 
                        /* global suspend if nothing connected for 1 second */
-                       if (!ports_active(uhci) && suspend_allowed(uhci)) {
+                       if (!any_ports_active(uhci) && suspend_allowed(uhci)) {
                                uhci->state = UHCI_SUSPENDING_GRACE;
                                uhci->state_end = jiffies + HZ;
                        }
                        break;
 
                case UHCI_SUSPENDING_GRACE:
-                       if (ports_active(uhci))
+                       if (any_ports_active(uhci))
                                uhci->state = UHCI_RUNNING;
                        else if (time_after_eq(jiffies, uhci->state_end))
                                suspend_hc(uhci);
@@ -302,58 +295,24 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
        }
 }
 
-static int init_stall_timer(struct usb_hcd *hcd);
-
-static void stall_callback(unsigned long ptr)
+static void stall_callback(unsigned long _uhci)
 {
-       struct usb_hcd *hcd = (struct usb_hcd *)ptr;
-       struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       struct urb_priv *up;
+       struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
        unsigned long flags;
 
        spin_lock_irqsave(&uhci->lock, flags);
        uhci_scan_schedule(uhci, NULL);
-
-       list_for_each_entry(up, &uhci->urb_list, urb_list) {
-               struct urb *u = up->urb;
-
-               spin_lock(&u->lock);
-
-               /* Check if the FSBR timed out */
-               if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
-                       uhci_fsbr_timeout(uhci, u);
-
-               spin_unlock(&u->lock);
-       }
-
-       /* Really disable FSBR */
-       if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
-               uhci->fsbrtimeout = 0;
-               uhci->skel_term_qh->link = UHCI_PTR_TERM;
-       }
+       check_fsbr(uhci);
 
        /* Poll for and perform state transitions */
        hc_state_transitions(uhci);
        if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
                uhci_check_ports(uhci);
 
-       init_stall_timer(hcd);
+       restart_timer(uhci);
        spin_unlock_irqrestore(&uhci->lock, flags);
 }
 
-static int init_stall_timer(struct usb_hcd *hcd)
-{
-       struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-
-       init_timer(&uhci->stall_timer);
-       uhci->stall_timer.function = stall_callback;
-       uhci->stall_timer.data = (unsigned long)hcd;
-       uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
-       add_timer(&uhci->stall_timer);
-
-       return 0;
-}
-
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -509,6 +468,10 @@ static int uhci_start(struct usb_hcd *hcd)
 
        init_waitqueue_head(&uhci->waitqh);
 
+       init_timer(&uhci->stall_timer);
+       uhci->stall_timer.function = stall_callback;
+       uhci->stall_timer.data = (unsigned long) uhci;
+
        uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
                        &dma_handle, 0);
        if (!uhci->fl) {
@@ -646,7 +609,7 @@ static int uhci_start(struct usb_hcd *hcd)
        if ((retval = start_hc(uhci)) != 0)
                goto err_alloc_skelqh;
 
-       init_stall_timer(hcd);
+       restart_timer(uhci);
 
        udev->speed = USB_SPEED_FULL;
 
index 4c45ba8390f8a51fa9750e534bd2ef0618caf2d1..ddb19cbf4b7537ad39a1cdb0475531fd0920f2c5 100644 (file)
@@ -33,6 +33,22 @@ static __u8 root_hub_hub_des[] =
 /* status change bits:  nonzero writes will clear */
 #define RWC_BITS       (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
 
+/* A port that either is connected or has a changed-bit set will prevent
+ * us from AUTO_STOPPING.
+ */
+static int any_ports_active(struct uhci_hcd *uhci)
+{
+       int port;
+
+       for (port = 0; port < uhci->rh_numports; ++port) {
+               if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
+                               (USBPORTSC_CCS | RWC_BITS)) ||
+                               test_bit(port, &uhci->port_c_suspend))
+                       return 1;
+       }
+       return 0;
+}
+
 static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
index 2a7c19501f248386138591962f4a5899e1c99947..f5c75885f7bebd367c53ecdaffa127b707f7af7a 100644 (file)
@@ -1537,3 +1537,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
        /* Wake up anyone waiting for an URB to complete */
        wake_up_all(&uhci->waitqh);
 }
+
+static void check_fsbr(struct uhci_hcd *uhci)
+{
+       struct urb_priv *up;
+
+       list_for_each_entry(up, &uhci->urb_list, urb_list) {
+               struct urb *u = up->urb;
+
+               spin_lock(&u->lock);
+
+               /* Check if the FSBR timed out */
+               if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
+                       uhci_fsbr_timeout(uhci, u);
+
+               spin_unlock(&u->lock);
+       }
+
+       /* Really disable FSBR */
+       if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
+               uhci->fsbrtimeout = 0;
+               uhci->skel_term_qh->link = UHCI_PTR_TERM;
+       }
+}