Skip to content

Commit

Permalink
USB: EHCI: EHCI 1.1 addendum: Enable Per-port change detect bits
Browse files Browse the repository at this point in the history
This patch will enable Per-port event feature defined in EHCI 1.1
addendum. This feature addresses an issue where HCD is currently
required to read and parse PORTSC for all enabled root hub ports. With
this patch, the overhead will be reduced.

Signed-off-by: Alek Du <alek.du@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alek Du authored and Greg Kroah-Hartman committed Aug 10, 2010
1 parent 48f2497 commit 5a9cdf3
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
19 changes: 17 additions & 2 deletions drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,11 @@ static int ehci_init(struct usb_hcd *hcd)
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
log2_irq_thresh = 0;
temp = 1 << (16 + log2_irq_thresh);
if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) {
ehci->has_ppcd = 1;
ehci_dbg(ehci, "enable per-port change event\n");
temp |= CMD_PPCEE;
}
if (HCC_CANPARK(hcc_params)) {
/* HW default park == 3, on hardware that supports it (like
* NVidia and ALI silicon), maximizes throughput on the async
Expand Down Expand Up @@ -782,6 +787,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* remote wakeup [4.3.1] */
if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
u32 ppcd = 0;

/* kick root hub later */
pcd_status = status;
Expand All @@ -790,9 +796,18 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
if (!(cmd & CMD_RUN))
usb_hcd_resume_root_hub(hcd);

/* get per-port change detect bits */
if (ehci->has_ppcd)
ppcd = status >> 16;

while (i--) {
int pstatus = ehci_readl(ehci,
&ehci->regs->port_status [i]);
int pstatus;

/* leverage per-port change bits feature */
if (ehci->has_ppcd && !(ppcd & (1 << i)))
continue;
pstatus = ehci_readl(ehci,
&ehci->regs->port_status[i]);

if (pstatus & PORT_OWNER)
continue;
Expand Down
9 changes: 9 additions & 0 deletions drivers/usb/host/ehci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
u32 mask;
int ports, i, retval = 1;
unsigned long flags;
u32 ppcd = 0;

/* if !USB_SUSPEND, root hub timers won't get shut down ... */
if (!HC_IS_RUNNING(hcd->state))
Expand Down Expand Up @@ -632,7 +633,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)

/* port N changes (bit N)? */
spin_lock_irqsave (&ehci->lock, flags);

/* get per-port change detect bits */
if (ehci->has_ppcd)
ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;

for (i = 0; i < ports; i++) {
/* leverage per-port change bits feature */
if (ehci->has_ppcd && !(ppcd & (1 << i)))
continue;
temp = ehci_readl(ehci, &ehci->regs->port_status [i]);

/*
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ struct ehci_hcd { /* one per controller */
__hc32 *ohci_hcctrl_reg;
unsigned has_hostpc:1;
unsigned has_lpm:1; /* support link power management */
unsigned has_ppcd:1; /* support per-port change bits */
u8 sbrn; /* packed release number */

/* irq statistics */
Expand Down

0 comments on commit 5a9cdf3

Please sign in to comment.