[PATCH] USB UHCI: Minor improvements
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>
This commit is contained in:
parent
014e73c99a
commit
f5946f8220
|
@ -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 */
|
/* 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-hub.c"
|
||||||
#include "uhci-debug.c"
|
#include "uhci-debug.c"
|
||||||
#include "uhci-q.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)
|
static int suspend_allowed(struct uhci_hcd *uhci)
|
||||||
{
|
{
|
||||||
unsigned long io_addr = uhci->io_addr;
|
unsigned long io_addr = uhci->io_addr;
|
||||||
|
@ -270,14 +263,14 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
|
||||||
case UHCI_RUNNING:
|
case UHCI_RUNNING:
|
||||||
|
|
||||||
/* global suspend if nothing connected for 1 second */
|
/* 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 = UHCI_SUSPENDING_GRACE;
|
||||||
uhci->state_end = jiffies + HZ;
|
uhci->state_end = jiffies + HZ;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UHCI_SUSPENDING_GRACE:
|
case UHCI_SUSPENDING_GRACE:
|
||||||
if (ports_active(uhci))
|
if (any_ports_active(uhci))
|
||||||
uhci->state = UHCI_RUNNING;
|
uhci->state = UHCI_RUNNING;
|
||||||
else if (time_after_eq(jiffies, uhci->state_end))
|
else if (time_after_eq(jiffies, uhci->state_end))
|
||||||
suspend_hc(uhci);
|
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 _uhci)
|
||||||
|
|
||||||
static void stall_callback(unsigned long ptr)
|
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd = (struct usb_hcd *)ptr;
|
struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
|
||||||
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
|
||||||
struct urb_priv *up;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&uhci->lock, flags);
|
spin_lock_irqsave(&uhci->lock, flags);
|
||||||
uhci_scan_schedule(uhci, NULL);
|
uhci_scan_schedule(uhci, NULL);
|
||||||
|
check_fsbr(uhci);
|
||||||
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 */
|
/* Poll for and perform state transitions */
|
||||||
hc_state_transitions(uhci);
|
hc_state_transitions(uhci);
|
||||||
if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
|
if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
|
||||||
uhci_check_ports(uhci);
|
uhci_check_ports(uhci);
|
||||||
|
|
||||||
init_stall_timer(hcd);
|
restart_timer(uhci);
|
||||||
spin_unlock_irqrestore(&uhci->lock, flags);
|
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)
|
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);
|
||||||
|
@ -509,6 +468,10 @@ 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) {
|
||||||
|
@ -646,7 +609,7 @@ static int uhci_start(struct usb_hcd *hcd)
|
||||||
if ((retval = start_hc(uhci)) != 0)
|
if ((retval = start_hc(uhci)) != 0)
|
||||||
goto err_alloc_skelqh;
|
goto err_alloc_skelqh;
|
||||||
|
|
||||||
init_stall_timer(hcd);
|
restart_timer(uhci);
|
||||||
|
|
||||||
udev->speed = USB_SPEED_FULL;
|
udev->speed = USB_SPEED_FULL;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,22 @@ static __u8 root_hub_hub_des[] =
|
||||||
/* status change bits: nonzero writes will clear */
|
/* status change bits: nonzero writes will clear */
|
||||||
#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
|
#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)
|
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);
|
||||||
|
|
|
@ -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 anyone waiting for an URB to complete */
|
||||||
wake_up_all(&uhci->waitqh);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue