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;
static kmem_cache_t *uhci_up_cachep; /* urb_priv */
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 */
#define IDLE_TIMEOUT msecs_to_jiffies(50)
......@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci);
#include "uhci-debug.c"
#include "uhci-q.c"
static int init_stall_timer(struct usb_hcd *hcd);
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)
static int ports_active(struct uhci_hcd *uhci)
{
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);
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);
for (i = 0; i < uhci->rh_numports; i++)
connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
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 short status;
int i;
/*
* Read the interrupt status, and write it back to clear the
* interrupt cause. Contrary to the UHCI specification, the
* "HC Halted" status bit is persistent: it is RO, not R/WC.
if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
return 1;
/* 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)) {
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 */
}
/* 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;
}
if (status & USBSTS_RD)
uhci->resume_detect = 1;
spin_lock(&uhci->lock);
uhci_scan_schedule(uhci, regs);
spin_unlock(&uhci->lock);
return IRQ_HANDLED;
return 1;
}
static void reset_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;
int connection = 0;
int i;
for (i = 0; i < uhci->rh_numports; i++)
connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
int timeout = 10;
return connection;
}
/*
* 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);
}
static int suspend_allowed(struct uhci_hcd *uhci)
{
unsigned long io_addr = uhci->io_addr;
int i;
/* Mark controller as running before we enable interrupts */
uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
return 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);
/* 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.
*/
/* Start at frame 0 */
outw(0, io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
/* 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;
}
/* Run and mark it configured with a 64-byte max packet */
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 1;
return 0;
}
static void hc_state_transitions(struct uhci_hcd *uhci)
......@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
}
}
/*
* 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)
static int init_stall_timer(struct usb_hcd *hcd);
static void stall_callback(unsigned long ptr)
{
if (!uhci->is_stopped)
uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
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 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;
int timeout = 10;
unsigned short status;
/*
* 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.
* Read the interrupt status, and write it back to clear the
* interrupt cause. Contrary to the UHCI specification, the
* "HC Halted" status bit is persistent: it is RO, not R/WC.
*/
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;
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)) {
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 */
uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
/* 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);
if (status & USBSTS_RD)
uhci->resume_detect = 1;
/* Start at frame 0 */
outw(0, io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
spin_lock(&uhci->lock);
uhci_scan_schedule(uhci, regs);
spin_unlock(&uhci->lock);
/* Run and mark it configured with a 64-byte max packet */
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 IRQ_HANDLED;
}
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