aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6fcffe15a005..ac0f7a4b0341 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -36,6 +36,7 @@
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h> 37#include <linux/debugfs.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/uaccess.h>
39 40
40#include <asm/byteorder.h> 41#include <asm/byteorder.h>
41#include <asm/io.h> 42#include <asm/io.h>
@@ -78,7 +79,13 @@ static const char hcd_name [] = "ehci_hcd";
78#define EHCI_TUNE_RL_TT 0 79#define EHCI_TUNE_RL_TT 0
79#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ 80#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
80#define EHCI_TUNE_MULT_TT 1 81#define EHCI_TUNE_MULT_TT 1
81#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ 82/*
83 * Some drivers think it's safe to schedule isochronous transfers more than
84 * 256 ms into the future (partly as a result of an old bug in the scheduling
85 * code). In an attempt to avoid trouble, we will use a minimum scheduling
86 * length of 512 frames instead of 256.
87 */
88#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */
82 89
83#define EHCI_IAA_MSECS 10 /* arbitrary */ 90#define EHCI_IAA_MSECS 10 /* arbitrary */
84#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ 91#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
@@ -100,6 +107,11 @@ static int ignore_oc = 0;
100module_param (ignore_oc, bool, S_IRUGO); 107module_param (ignore_oc, bool, S_IRUGO);
101MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); 108MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
102 109
110/* for link power management(LPM) feature */
111static unsigned int hird;
112module_param(hird, int, S_IRUGO);
113MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
114
103#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) 115#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
104 116
105/*-------------------------------------------------------------------------*/ 117/*-------------------------------------------------------------------------*/
@@ -304,6 +316,7 @@ static void end_unlink_async(struct ehci_hcd *ehci);
304static void ehci_work(struct ehci_hcd *ehci); 316static void ehci_work(struct ehci_hcd *ehci);
305 317
306#include "ehci-hub.c" 318#include "ehci-hub.c"
319#include "ehci-lpm.c"
307#include "ehci-mem.c" 320#include "ehci-mem.c"
308#include "ehci-q.c" 321#include "ehci-q.c"
309#include "ehci-sched.c" 322#include "ehci-sched.c"
@@ -577,6 +590,11 @@ static int ehci_init(struct usb_hcd *hcd)
577 if (log2_irq_thresh < 0 || log2_irq_thresh > 6) 590 if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
578 log2_irq_thresh = 0; 591 log2_irq_thresh = 0;
579 temp = 1 << (16 + log2_irq_thresh); 592 temp = 1 << (16 + log2_irq_thresh);
593 if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) {
594 ehci->has_ppcd = 1;
595 ehci_dbg(ehci, "enable per-port change event\n");
596 temp |= CMD_PPCEE;
597 }
580 if (HCC_CANPARK(hcc_params)) { 598 if (HCC_CANPARK(hcc_params)) {
581 /* HW default park == 3, on hardware that supports it (like 599 /* HW default park == 3, on hardware that supports it (like
582 * NVidia and ALI silicon), maximizes throughput on the async 600 * NVidia and ALI silicon), maximizes throughput on the async
@@ -603,10 +621,22 @@ static int ehci_init(struct usb_hcd *hcd)
603 default: BUG(); 621 default: BUG();
604 } 622 }
605 } 623 }
624 if (HCC_LPM(hcc_params)) {
625 /* support link power management EHCI 1.1 addendum */
626 ehci_dbg(ehci, "support lpm\n");
627 ehci->has_lpm = 1;
628 if (hird > 0xf) {
629 ehci_dbg(ehci, "hird %d invalid, use default 0",
630 hird);
631 hird = 0;
632 }
633 temp |= hird << 24;
634 }
606 ehci->command = temp; 635 ehci->command = temp;
607 636
608 /* Accept arbitrarily long scatter-gather lists */ 637 /* Accept arbitrarily long scatter-gather lists */
609 hcd->self.sg_tablesize = ~0; 638 if (!(hcd->driver->flags & HCD_LOCAL_MEM))
639 hcd->self.sg_tablesize = ~0;
610 return 0; 640 return 0;
611} 641}
612 642
@@ -619,7 +649,6 @@ static int ehci_run (struct usb_hcd *hcd)
619 u32 hcc_params; 649 u32 hcc_params;
620 650
621 hcd->uses_new_polling = 1; 651 hcd->uses_new_polling = 1;
622 hcd->poll_rh = 0;
623 652
624 /* EHCI spec section 4.1 */ 653 /* EHCI spec section 4.1 */
625 if ((retval = ehci_reset(ehci)) != 0) { 654 if ((retval = ehci_reset(ehci)) != 0) {
@@ -764,6 +793,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
764 /* remote wakeup [4.3.1] */ 793 /* remote wakeup [4.3.1] */
765 if (status & STS_PCD) { 794 if (status & STS_PCD) {
766 unsigned i = HCS_N_PORTS (ehci->hcs_params); 795 unsigned i = HCS_N_PORTS (ehci->hcs_params);
796 u32 ppcd = 0;
767 797
768 /* kick root hub later */ 798 /* kick root hub later */
769 pcd_status = status; 799 pcd_status = status;
@@ -772,9 +802,18 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
772 if (!(cmd & CMD_RUN)) 802 if (!(cmd & CMD_RUN))
773 usb_hcd_resume_root_hub(hcd); 803 usb_hcd_resume_root_hub(hcd);
774 804
805 /* get per-port change detect bits */
806 if (ehci->has_ppcd)
807 ppcd = status >> 16;
808
775 while (i--) { 809 while (i--) {
776 int pstatus = ehci_readl(ehci, 810 int pstatus;
777 &ehci->regs->port_status [i]); 811
812 /* leverage per-port change bits feature */
813 if (ehci->has_ppcd && !(ppcd & (1 << i)))
814 continue;
815 pstatus = ehci_readl(ehci,
816 &ehci->regs->port_status[i]);
778 817
779 if (pstatus & PORT_OWNER) 818 if (pstatus & PORT_OWNER)
780 continue; 819 continue;