[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:
parent
f1a15606d5
commit
1f09df8bfe
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue