aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlek Du <alek.du@intel.com>2010-06-04 03:47:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:35 -0400
commit5a9cdf332eae724b11906cb1712e3a662eba32b2 (patch)
tree67aad1a4e795b2b26e4e320305accba16c4d201e /drivers
parent48f24970144479c29b8cee6d2e1dbedf6dcf9cfb (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')
-rw-r--r--drivers/usb/host/ehci-hcd.c19
-rw-r--r--drivers/usb/host/ehci-hub.c9
-rw-r--r--drivers/usb/host/ehci.h1
3 files changed, 27 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)
584 if (log2_irq_thresh < 0 || log2_irq_thresh > 6) 584 if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
585 log2_irq_thresh = 0; 585 log2_irq_thresh = 0;
586 temp = 1 << (16 + log2_irq_thresh); 586 temp = 1 << (16 + log2_irq_thresh);
587 if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) {
588 ehci->has_ppcd = 1;
589 ehci_dbg(ehci, "enable per-port change event\n");
590 temp |= CMD_PPCEE;
591 }
587 if (HCC_CANPARK(hcc_params)) { 592 if (HCC_CANPARK(hcc_params)) {
588 /* HW default park == 3, on hardware that supports it (like 593 /* HW default park == 3, on hardware that supports it (like
589 * NVidia and ALI silicon), maximizes throughput on the async 594 * NVidia and ALI silicon), maximizes throughput on the async
@@ -782,6 +787,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
782 /* remote wakeup [4.3.1] */ 787 /* remote wakeup [4.3.1] */
783 if (status & STS_PCD) { 788 if (status & STS_PCD) {
784 unsigned i = HCS_N_PORTS (ehci->hcs_params); 789 unsigned i = HCS_N_PORTS (ehci->hcs_params);
790 u32 ppcd = 0;
785 791
786 /* kick root hub later */ 792 /* kick root hub later */
787 pcd_status = status; 793 pcd_status = status;
@@ -790,9 +796,18 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
790 if (!(cmd & CMD_RUN)) 796 if (!(cmd & CMD_RUN))
791 usb_hcd_resume_root_hub(hcd); 797 usb_hcd_resume_root_hub(hcd);
792 798
799 /* get per-port change detect bits */
800 if (ehci->has_ppcd)
801 ppcd = status >> 16;
802
793 while (i--) { 803 while (i--) {
794 int pstatus = ehci_readl(ehci, 804 int pstatus;
795 &ehci->regs->port_status [i]); 805
806 /* leverage per-port change bits feature */
807 if (ehci->has_ppcd && !(ppcd & (1 << i)))
808 continue;
809 pstatus = ehci_readl(ehci,
810 &ehci->regs->port_status[i]);
796 811
797 if (pstatus & PORT_OWNER) 812 if (pstatus & PORT_OWNER)
798 continue; 813 continue;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 8a28dae8a375..84e792d71c22 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -603,6 +603,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
603 u32 mask; 603 u32 mask;
604 int ports, i, retval = 1; 604 int ports, i, retval = 1;
605 unsigned long flags; 605 unsigned long flags;
606 u32 ppcd = 0;
606 607
607 /* if !USB_SUSPEND, root hub timers won't get shut down ... */ 608 /* if !USB_SUSPEND, root hub timers won't get shut down ... */
608 if (!HC_IS_RUNNING(hcd->state)) 609 if (!HC_IS_RUNNING(hcd->state))
@@ -632,7 +633,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
632 633
633 /* port N changes (bit N)? */ 634 /* port N changes (bit N)? */
634 spin_lock_irqsave (&ehci->lock, flags); 635 spin_lock_irqsave (&ehci->lock, flags);
636
637 /* get per-port change detect bits */
638 if (ehci->has_ppcd)
639 ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;
640
635 for (i = 0; i < ports; i++) { 641 for (i = 0; i < ports; i++) {
642 /* leverage per-port change bits feature */
643 if (ehci->has_ppcd && !(ppcd & (1 << i)))
644 continue;
636 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 645 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
637 646
638 /* 647 /*
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 21f30a0c3d2f..e6c57cc416f6 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -141,6 +141,7 @@ struct ehci_hcd { /* one per controller */
141 __hc32 *ohci_hcctrl_reg; 141 __hc32 *ohci_hcctrl_reg;
142 unsigned has_hostpc:1; 142 unsigned has_hostpc:1;
143 unsigned has_lpm:1; /* support link power management */ 143 unsigned has_lpm:1; /* support link power management */
144 unsigned has_ppcd:1; /* support per-port change bits */
144 u8 sbrn; /* packed release number */ 145 u8 sbrn; /* packed release number */
145 146
146 /* irq statistics */ 147 /* irq statistics */