Commit 014e73c9 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB UHCI: subroutine reordering

This patch moves a few subroutines around in the uhci-hcd source file.
Nothing else is changed.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 72ebddb5
...@@ -90,7 +90,6 @@ static char *errbuf; ...@@ -90,7 +90,6 @@ static char *errbuf;
static kmem_cache_t *uhci_up_cachep; /* urb_priv */ static kmem_cache_t *uhci_up_cachep; /* urb_priv */
static void uhci_get_current_frame_number(struct uhci_hcd *uhci); static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
static void hc_state_transitions(struct uhci_hcd *uhci);
/* If a transfer is still active after this much time, turn off FSBR */ /* If a transfer is still active after this much time, turn off FSBR */
#define IDLE_TIMEOUT msecs_to_jiffies(50) #define IDLE_TIMEOUT msecs_to_jiffies(50)
...@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci); ...@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci);
#include "uhci-debug.c" #include "uhci-debug.c"
#include "uhci-q.c" #include "uhci-q.c"
static int init_stall_timer(struct usb_hcd *hcd); static int ports_active(struct uhci_hcd *uhci)
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;
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;
}
/* 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);
spin_unlock_irqrestore(&uhci->lock, flags);
}
static int init_stall_timer(struct usb_hcd *hcd)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long io_addr = uhci->io_addr;
int connection = 0;
int i;
init_timer(&uhci->stall_timer); for (i = 0; i < uhci->rh_numports; i++)
uhci->stall_timer.function = stall_callback; connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
uhci->stall_timer.data = (unsigned long)hcd;
uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
add_timer(&uhci->stall_timer);
return 0; return connection;
} }
static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) static int suspend_allowed(struct uhci_hcd *uhci)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long io_addr = uhci->io_addr; unsigned long io_addr = uhci->io_addr;
unsigned short status; int i;
/* if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
* Read the interrupt status, and write it back to clear the return 1;
* interrupt cause. Contrary to the UHCI specification, the
* "HC Halted" status bit is persistent: it is RO, not R/WC. /* Some of Intel's USB controllers have a bug that causes false
* resume indications if any port has an over current condition.
* To prevent problems, we will not allow a global suspend if
* any ports are OC.
*
* Some motherboards using Intel's chipsets (but not using all
* the USB ports) appear to hardwire the over current inputs active
* to disable the USB ports.
*/ */
status = inw(io_addr + USBSTS);
if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */
return IRQ_NONE;
outw(status, io_addr + USBSTS); /* Clear it */
if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { /* check for over current condition on any port */
if (status & USBSTS_HSE) for (i = 0; i < uhci->rh_numports; i++) {
dev_err(uhci_dev(uhci), "host system error, " if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
"PCI problems?\n"); return 0;
if (status & USBSTS_HCPE)
dev_err(uhci_dev(uhci), "host controller process "
"error, something bad happened!\n");
if ((status & USBSTS_HCH) && uhci->state > 0) {
dev_err(uhci_dev(uhci), "host controller halted, "
"very bad!\n");
/* FIXME: Reset the controller, fix the offending TD */
}
} }
if (status & USBSTS_RD) return 1;
uhci->resume_detect = 1;
spin_lock(&uhci->lock);
uhci_scan_schedule(uhci, regs);
spin_unlock(&uhci->lock);
return IRQ_HANDLED;
} }
static void reset_hc(struct uhci_hcd *uhci) static void reset_hc(struct uhci_hcd *uhci)
...@@ -276,43 +222,46 @@ static void wakeup_hc(struct uhci_hcd *uhci) ...@@ -276,43 +222,46 @@ static void wakeup_hc(struct uhci_hcd *uhci)
} }
} }
static int ports_active(struct uhci_hcd *uhci) static int start_hc(struct uhci_hcd *uhci)
{ {
unsigned long io_addr = uhci->io_addr; unsigned long io_addr = uhci->io_addr;
int connection = 0; int timeout = 10;
int i;
for (i = 0; i < uhci->rh_numports; i++) /*
connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); * Reset the HC - this will force us to get a
* new notification of any already connected
* ports due to the virtual disconnect that it
* implies.
*/
outw(USBCMD_HCRESET, io_addr + USBCMD);
while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
if (--timeout < 0) {
dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
return -ETIMEDOUT;
}
msleep(1);
}
return connection; /* Mark controller as running before we enable interrupts */
} uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
static int suspend_allowed(struct uhci_hcd *uhci) /* Turn on PIRQ and all interrupts */
{ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
unsigned long io_addr = uhci->io_addr; USBLEGSUP_DEFAULT);
int i; outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
io_addr + USBINTR);
if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) /* Start at frame 0 */
return 1; outw(0, io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
/* Some of Intel's USB controllers have a bug that causes false /* Run and mark it configured with a 64-byte max packet */
* resume indications if any port has an over current condition. uhci->state = UHCI_RUNNING_GRACE;
* To prevent problems, we will not allow a global suspend if uhci->state_end = jiffies + HZ;
* any ports are OC. outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
* uhci->is_stopped = 0;
* Some motherboards using Intel's chipsets (but not using all
* the USB ports) appear to hardwire the over current inputs active
* to disable the USB ports.
*/
/* check for over current condition on any port */
for (i = 0; i < uhci->rh_numports; i++) {
if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
return 0; return 0;
}
return 1;
} }
static void hc_state_transitions(struct uhci_hcd *uhci) static void hc_state_transitions(struct uhci_hcd *uhci)
...@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci) ...@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
} }
} }
/* static int init_stall_timer(struct usb_hcd *hcd);
* Store the current frame number in uhci->frame_number if the controller
* is runnning static void stall_callback(unsigned long ptr)
*/
static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
{ {
if (!uhci->is_stopped) struct usb_hcd *hcd = (struct usb_hcd *)ptr;
uhci->frame_number = inw(uhci->io_addr + USBFRNUM); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
struct urb_priv *up;
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;
}
/* 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);
spin_unlock_irqrestore(&uhci->lock, flags);
} }
static int start_hc(struct uhci_hcd *uhci) 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);
unsigned long io_addr = uhci->io_addr; unsigned long io_addr = uhci->io_addr;
int timeout = 10; unsigned short status;
/* /*
* Reset the HC - this will force us to get a * Read the interrupt status, and write it back to clear the
* new notification of any already connected * interrupt cause. Contrary to the UHCI specification, the
* ports due to the virtual disconnect that it * "HC Halted" status bit is persistent: it is RO, not R/WC.
* implies.
*/ */
outw(USBCMD_HCRESET, io_addr + USBCMD); status = inw(io_addr + USBSTS);
while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */
if (--timeout < 0) { return IRQ_NONE;
dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); outw(status, io_addr + USBSTS); /* Clear it */
return -ETIMEDOUT;
if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
if (status & USBSTS_HSE)
dev_err(uhci_dev(uhci), "host system error, "
"PCI problems?\n");
if (status & USBSTS_HCPE)
dev_err(uhci_dev(uhci), "host controller process "
"error, something bad happened!\n");
if ((status & USBSTS_HCH) && uhci->state > 0) {
dev_err(uhci_dev(uhci), "host controller halted, "
"very bad!\n");
/* FIXME: Reset the controller, fix the offending TD */
} }
msleep(1);
} }
/* Mark controller as running before we enable interrupts */ if (status & USBSTS_RD)
uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; uhci->resume_detect = 1;
/* Turn on PIRQ and all interrupts */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
USBLEGSUP_DEFAULT);
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
io_addr + USBINTR);
/* Start at frame 0 */ spin_lock(&uhci->lock);
outw(0, io_addr + USBFRNUM); uhci_scan_schedule(uhci, regs);
outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); spin_unlock(&uhci->lock);
/* Run and mark it configured with a 64-byte max packet */ return IRQ_HANDLED;
uhci->state = UHCI_RUNNING_GRACE; }
uhci->state_end = jiffies + HZ;
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
uhci->is_stopped = 0;
return 0; /*
* Store the current frame number in uhci->frame_number if the controller
* is runnning
*/
static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
{
if (!uhci->is_stopped)
uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment