diff options
author | Alek Du <alek.du@intel.com> | 2010-06-04 15:47:56 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 14:35:35 -0700 |
commit | 5a9cdf332eae724b11906cb1712e3a662eba32b2 (patch) | |
tree | 67aad1a4e795b2b26e4e320305accba16c4d201e /drivers/usb/host/ehci-hcd.c | |
parent | 48f24970144479c29b8cee6d2e1dbedf6dcf9cfb (diff) |
USB: EHCI: EHCI 1.1 addendum: Enable Per-port change detect bits
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>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index baf9b648bb1f..8697ad19f313 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -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 @@ -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; @@ -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; |