diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Kconfig | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 67 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mem.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 127 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 14 |
6 files changed, 3 insertions, 215 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 7dd73546bf43..63436892688c 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -6,6 +6,9 @@ menuconfig USB_SUPPORT bool "USB support" depends on HAS_IOMEM default y + ---help--- + This option adds core support for Universal Serial Bus (USB). + You will also need drivers from the following menu to make use of it. if USB_SUPPORT diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c4e15ed1405a..35cdba10411b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -275,58 +275,6 @@ static void ehci_work(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_CPU_FREQ - -#include <linux/cpufreq.h> - -static void ehci_cpufreq_pause (struct ehci_hcd *ehci) -{ - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - if (!ehci->cpufreq_changing++) - qh_inactivate_split_intr_qhs(ehci); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static void ehci_cpufreq_unpause (struct ehci_hcd *ehci) -{ - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - if (!--ehci->cpufreq_changing) - qh_reactivate_split_intr_qhs(ehci); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -/* - * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when - * EHCI controllers that don't cache many uframes get delayed trying to - * read main memory during CPU frequency transitions. This can cause - * split interrupt transactions to not be completed in the required uframe. - * This has been observed on the Broadcom/ServerWorks HT1000 controller. - */ -static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd, - cpufreq_transition); - - switch (val) { - case CPUFREQ_PRECHANGE: - ehci_cpufreq_pause(ehci); - break; - case CPUFREQ_POSTCHANGE: - ehci_cpufreq_unpause(ehci); - break; - } - return 0; -} - -#endif - -/*-------------------------------------------------------------------------*/ - static void ehci_watchdog (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; @@ -460,10 +408,6 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_writel(ehci, 0, &ehci->regs->intr_enable); spin_unlock_irq(&ehci->lock); -#ifdef CONFIG_CPU_FREQ - cpufreq_unregister_notifier(&ehci->cpufreq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -#endif /* let companion controllers work when we aren't */ ehci_writel(ehci, 0, &ehci->regs->configured_flag); @@ -569,17 +513,6 @@ static int ehci_init(struct usb_hcd *hcd) } ehci->command = temp; -#ifdef CONFIG_CPU_FREQ - INIT_LIST_HEAD(&ehci->split_intr_qhs); - /* - * If the EHCI controller caches enough uframes, this probably - * isn't needed unless there are so many low/full speed devices - * that the controller's can't cache it all. - */ - ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier; - cpufreq_register_notifier(&ehci->cpufreq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -#endif return 0; } diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 8816d09903d0..0431397836f6 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -94,9 +94,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) qh->qh_dma = dma; // INIT_LIST_HEAD (&qh->qh_list); INIT_LIST_HEAD (&qh->qtd_list); -#ifdef CONFIG_CPU_FREQ - INIT_LIST_HEAD (&qh->split_intr_qhs); -#endif /* dummy td enables safe urb queuing */ qh->dummy = ehci_qtd_alloc (ehci, flags); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 2284028f8aa5..140bfa423e07 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -312,10 +312,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) struct urb *urb; u32 token = 0; - /* ignore QHs that are currently inactive */ - if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE)) - break; - qtd = list_entry (entry, struct ehci_qtd, qtd_list); urb = qtd->urb; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index d4a8ace49676..e682f2342ef8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -479,109 +479,6 @@ static int disable_periodic (struct ehci_hcd *ehci) } /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_CPU_FREQ - -static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - int now; /* current (frame * 8) + uframe */ - int prev_start, next_start; /* uframes from/to split start */ - int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK); - int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8); - int split_duration = end_uframe - start_uframe; - - now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3); - - next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now) - % (qh->period << 3); - prev_start = (qh->period << 3) - next_start; - - /* - * Make sure there will be at least one uframe when qh is safe. - */ - if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration)) - /* never safe */ - return -EINVAL; - - /* - * Wait 1 uframe after transaction should have started, to make - * sure controller has time to write back overlay, so we can - * check QTD_STS_STS to see if transaction is in progress. - */ - if ((next_start > ehci->i_thresh) && (prev_start > 1)) - /* safe to set "i" bit if split isn't in progress */ - return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1; - else - return 0; -} - -/* Set inactivate bit for all the split interrupt QHs. */ -static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - int not_done, safe; - u32 inactivate = INACTIVATE_BIT(ehci); - u32 active = ACTIVE_BIT(ehci); - - do { - not_done = 0; - list_for_each_entry(qh, &ehci->split_intr_qhs, - split_intr_qhs) { - if (qh->hw_info1 & inactivate) - /* already off */ - continue; - /* - * To avoid setting "I" after the start split happens, - * don't set it if the QH might be cached in the - * controller. Some HCs (Broadcom/ServerWorks HT1000) - * will stop in the middle of a split transaction when - * the "I" bit is set. - */ - safe = safe_to_modify_i(ehci, qh); - if (safe == 0) { - not_done = 1; - } else if (safe > 0) { - qh->was_active = qh->hw_token & active; - qh->hw_info1 |= inactivate; - } - } - } while (not_done); - wmb(); -} - -static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - u32 token; - int not_done, safe; - u32 inactivate = INACTIVATE_BIT(ehci); - u32 active = ACTIVE_BIT(ehci); - u32 halt = HALT_BIT(ehci); - - do { - not_done = 0; - list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) { - if (!(qh->hw_info1 & inactivate)) /* already on */ - continue; - /* - * Don't reactivate if cached, or controller might - * overwrite overlay after we modify it! - */ - safe = safe_to_modify_i(ehci, qh); - if (safe == 0) { - not_done = 1; - } else if (safe > 0) { - /* See EHCI 1.0 section 4.15.2.4. */ - token = qh->hw_token; - qh->hw_token = (token | halt) & ~active; - wmb(); - qh->hw_info1 &= ~inactivate; - wmb(); - qh->hw_token = (token & ~halt) | qh->was_active; - } - } - } while (not_done); -} -#endif /* periodic schedule slots have iso tds (normal or split) first, then a * sparse tree for active interrupt transfers. @@ -599,17 +496,6 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); -#ifdef CONFIG_CPU_FREQ - /* - * If low/full speed interrupt QHs are inactive (because of - * cpufreq changing processor speeds), start QH with I flag set-- - * it will automatically be cleared when cpufreq is done. - */ - if (ehci->cpufreq_changing) - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) - qh->hw_info1 |= INACTIVATE_BIT(ehci); -#endif - /* high bandwidth, or otherwise every microframe */ if (period == 0) period = 1; @@ -658,12 +544,6 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) ? ((qh->usecs + qh->c_usecs) / qh->period) : (qh->usecs * 8); -#ifdef CONFIG_CPU_FREQ - /* add qh to list of low/full speed interrupt QHs, if applicable */ - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { - list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs); - } -#endif /* maybe enable periodic schedule processing */ if (!ehci->periodic_sched++) return enable_periodic (ehci); @@ -683,13 +563,6 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) // THEN // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); -#ifdef CONFIG_CPU_FREQ - /* remove qh from list of low/full speed interrupt QHs */ - if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { - list_del_init(&qh->split_intr_qhs); - } -#endif - /* high bandwidth, or otherwise part of every microframe */ if ((period = qh->period) == 0) period = 1; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2c68a04230c1..951d69fec513 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -71,12 +71,6 @@ struct ehci_hcd { /* one per controller */ __u32 hcs_params; /* cached register copy */ spinlock_t lock; -#ifdef CONFIG_CPU_FREQ - struct notifier_block cpufreq_transition; - int cpufreq_changing; - struct list_head split_intr_qhs; -#endif - /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; @@ -439,10 +433,6 @@ struct ehci_qh { __hc32 hw_next; /* see EHCI 3.6.1 */ __hc32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 -#define QH_INACTIVATE 0x00000080 - -#define INACTIVATE_BIT(ehci) cpu_to_hc32(ehci, QH_INACTIVATE) - __hc32 hw_info2; /* see EHCI 3.6.2 */ #define QH_SMASK 0x000000ff #define QH_CMASK 0x0000ff00 @@ -492,10 +482,6 @@ struct ehci_qh { unsigned short start; /* where polling starts */ #define NO_FRAME ((unsigned short)~0) /* pick new start */ struct usb_device *dev; /* access to TT */ -#ifdef CONFIG_CPU_FREQ - struct list_head split_intr_qhs; /* list of split qhs */ - __le32 was_active; /* active bit before "i" set */ -#endif } __attribute__ ((aligned (32))); /*-------------------------------------------------------------------------*/ |