diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 19 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 1 |
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 */ |