From 323640b7b92787f9b8a25906d021192786ab1615 Mon Sep 17 00:00:00 2001 From: Alek Du Date: Fri, 4 Jun 2010 15:47:56 +0800 Subject: [PATCH] --- yaml --- r: 207963 b: refs/heads/master c: 5a9cdf332eae724b11906cb1712e3a662eba32b2 h: refs/heads/master i: 207961: 4d5ebfd09b9fa21a9b0b6a3f8676f06ff071da6c 207959: e6ec3e974613f14259ff097cd5974261856be73b v: v3 --- [refs] | 2 +- trunk/drivers/usb/host/ehci-hcd.c | 19 +++++++++++++++++-- trunk/drivers/usb/host/ehci-hub.c | 9 +++++++++ trunk/drivers/usb/host/ehci.h | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index a55aaa748f56..b400f09ce71b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 48f24970144479c29b8cee6d2e1dbedf6dcf9cfb +refs/heads/master: 5a9cdf332eae724b11906cb1712e3a662eba32b2 diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index baf9b648bb1f..8697ad19f313 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/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; diff --git a/trunk/drivers/usb/host/ehci-hub.c b/trunk/drivers/usb/host/ehci-hub.c index 8a28dae8a375..84e792d71c22 100644 --- a/trunk/drivers/usb/host/ehci-hub.c +++ b/trunk/drivers/usb/host/ehci-hub.c @@ -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)) @@ -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]); /* diff --git a/trunk/drivers/usb/host/ehci.h b/trunk/drivers/usb/host/ehci.h index 21f30a0c3d2f..e6c57cc416f6 100644 --- a/trunk/drivers/usb/host/ehci.h +++ b/trunk/drivers/usb/host/ehci.h @@ -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 */