[PATCH] USB UHCI: remove the FSBR kernel timer

This patch (as558) removes from the UHCI driver a kernel timer used for
checking Full Speed Bandwidth Reclamation (FSBR).  The checking can be
done during normal root-hub polling; it doesn't need a separate timer.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Alan Stern 2005-09-05 13:59:51 -04:00 committed by Greg Kroah-Hartman
parent f1a15606d5
commit 1f09df8bfe
4 changed files with 32 additions and 54 deletions

View file

@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
/* to make sure it doesn't hog all of the bandwidth */ /* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5 #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-debug.c"
#include "uhci-q.c" #include "uhci-q.c"
#include "uhci-hub.c"
/* /*
* Make sure the controller is completely inactive, unable to * Make sure the controller is completely inactive, unable to
@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
{ {
reset_hc(uhci); reset_hc(uhci);
uhci->hc_inaccessible = 1; uhci->hc_inaccessible = 1;
del_timer(&uhci->stall_timer);
} }
/* /*
@ -287,8 +281,11 @@ __acquires(uhci->lock)
/* Enable resume-detect interrupts if they work. /* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode, still configured. * Then enter Global Suspend mode, still configured.
*/ */
int_enable = (resume_detect_interrupts_are_broken(uhci) ? uhci->working_RD = 1;
0 : USBINTR_RESUME); int_enable = USBINTR_RESUME;
if (resume_detect_interrupts_are_broken(uhci)) {
uhci->working_RD = int_enable = 0;
}
outw(int_enable, uhci->io_addr + USBINTR); outw(int_enable, uhci->io_addr + USBINTR);
outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
mb(); mb();
@ -315,7 +312,6 @@ __acquires(uhci->lock)
uhci->rh_state = new_state; uhci->rh_state = new_state;
uhci->is_stopped = UHCI_IS_STOPPED; uhci->is_stopped = UHCI_IS_STOPPED;
del_timer(&uhci->stall_timer);
uhci_to_hcd(uhci)->poll_rh = !int_enable; uhci_to_hcd(uhci)->poll_rh = !int_enable;
uhci_scan_schedule(uhci, NULL); uhci_scan_schedule(uhci, NULL);
@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
mb(); mb();
uhci->rh_state = UHCI_RH_RUNNING; uhci->rh_state = UHCI_RH_RUNNING;
uhci_to_hcd(uhci)->poll_rh = 1; uhci_to_hcd(uhci)->poll_rh = 1;
restart_timer(uhci);
} }
static void wakeup_rh(struct uhci_hcd *uhci) static void wakeup_rh(struct uhci_hcd *uhci)
@ -374,20 +369,6 @@ __acquires(uhci->lock)
mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
} }
static void stall_callback(unsigned long _uhci)
{
struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
unsigned long flags;
spin_lock_irqsave(&uhci->lock, flags);
uhci_scan_schedule(uhci, NULL);
check_fsbr(uhci);
if (!uhci->is_stopped)
restart_timer(uhci);
spin_unlock_irqrestore(&uhci->lock, flags);
}
static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
"host controller halted, " "host controller halted, "
"very bad!\n"); "very bad!\n");
hc_died(uhci); hc_died(uhci);
spin_unlock_irqrestore(&uhci->lock, flags);
return IRQ_HANDLED; /* Force a callback in case there are
* pending unlinks */
mod_timer(&hcd->rh_timer, jiffies);
} }
spin_unlock_irqrestore(&uhci->lock, flags); spin_unlock_irqrestore(&uhci->lock, flags);
} }
@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (status & USBSTS_RD) if (status & USBSTS_RD)
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
else {
spin_lock_irqsave(&uhci->lock, flags); spin_lock_irqsave(&uhci->lock, flags);
uhci_scan_schedule(uhci, regs); uhci_scan_schedule(uhci, regs);
spin_unlock_irqrestore(&uhci->lock, flags); spin_unlock_irqrestore(&uhci->lock, flags);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
init_waitqueue_head(&uhci->waitqh); 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), uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
&dma_handle, 0); &dma_handle, 0);
if (!uhci->fl) { if (!uhci->fl) {
@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
spin_lock_irq(&uhci->lock); spin_lock_irq(&uhci->lock);
reset_hc(uhci); if (!uhci->hc_inaccessible)
reset_hc(uhci);
uhci_scan_schedule(uhci, NULL); uhci_scan_schedule(uhci, NULL);
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
del_timer_sync(&uhci->stall_timer);
release_uhci(uhci); release_uhci(uhci);
} }
@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
*/ */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
uhci->hc_inaccessible = 1; uhci->hc_inaccessible = 1;
hcd->poll_rh = 0;
/* FIXME: Enable non-PME# remote wakeup? */ /* FIXME: Enable non-PME# remote wakeup? */
done: done:
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
if (rc == 0)
del_timer_sync(&hcd->rh_timer);
return rc; return rc;
} }
@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
spin_unlock_irq(&uhci->lock); spin_unlock_irq(&uhci->lock);
if (hcd->poll_rh) if (!uhci->working_RD) {
/* Suspended root hub needs to be polled */
hcd->poll_rh = 1;
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
}
return 0; return 0;
} }
#endif #endif

View file

@ -345,9 +345,6 @@ enum uhci_rh_state {
/* /*
* This describes the full uhci information. * This describes the full uhci information.
*
* Note how the "proper" USB information is just
* a subset of what the full implementation needs.
*/ */
struct uhci_hcd { struct uhci_hcd {
@ -360,8 +357,6 @@ struct uhci_hcd {
struct dma_pool *qh_pool; struct dma_pool *qh_pool;
struct dma_pool *td_pool; struct dma_pool *td_pool;
struct usb_bus *bus;
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
@ -380,6 +375,8 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */ unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */ unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int hc_inaccessible:1; /* HC is suspended or dead */ unsigned int hc_inaccessible:1; /* HC is suspended or dead */
unsigned int working_RD:1; /* Suspended root hub doesn't
need to be polled */
/* Support for port suspend/resume/reset */ /* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */ unsigned long port_c_suspend; /* Bit-arrays of ports */
@ -405,9 +402,7 @@ struct uhci_hcd {
/* List of URB's awaiting completion callback */ /* List of URB's awaiting completion callback */
struct list_head complete_list; /* P: uhci->lock */ struct list_head complete_list; /* P: uhci->lock */
int rh_numports; int rh_numports; /* Number of root-hub ports */
struct timer_list stall_timer;
wait_queue_head_t waitqh; /* endpoint_disable waiters */ wait_queue_head_t waitqh; /* endpoint_disable waiters */
}; };

View file

@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags; unsigned long flags;
int status; int status = 0;
spin_lock_irqsave(&uhci->lock, flags); spin_lock_irqsave(&uhci->lock, flags);
if (uhci->hc_inaccessible) {
status = 0;
goto done;
}
uhci_scan_schedule(uhci, NULL);
if (uhci->hc_inaccessible)
goto done;
check_fsbr(uhci);
uhci_check_ports(uhci); uhci_check_ports(uhci);
status = get_hub_status_data(uhci, buf); status = get_hub_status_data(uhci, buf);
switch (uhci->rh_state) { switch (uhci->rh_state) {

View file

@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
{ {
if (uhci->is_stopped) if (uhci->is_stopped)
mod_timer(&uhci->stall_timer, jiffies); mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
} }