diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 233 |
1 files changed, 90 insertions, 143 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b416a3fc995..81cda09b47e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -71,7 +71,6 @@ static const char hcd_name [] = "ehci_hcd"; -#undef VERBOSE_DEBUG #undef EHCI_URB_TRACE /* magic numbers that can affect system performance */ @@ -110,6 +109,9 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); #include "ehci.h" #include "pci-quirks.h" +static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], + struct ehci_tt *tt); + /* * The MosChip MCS9990 controller updates its microframe counter * a little before the frame counter, and occasionally we will read @@ -139,7 +141,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ /* - * handshake - spin reading hc until handshake completes or fails + * ehci_handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read * @mask: bits to look at in result of read * @done: value of those bits when handshake succeeds @@ -155,8 +157,8 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) * before driver shutdown. But it also seems to be caused by bugs in cardbus * bridge shutdown: shutting down the bridge before the devices using it. */ -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) +int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, + u32 mask, u32 done, int usec) { u32 result; @@ -172,6 +174,7 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, } while (usec > 0); return -ETIMEDOUT; } +EXPORT_SYMBOL_GPL(ehci_handshake); /* check TDI/ARC silicon is in host mode */ static int tdi_in_host_mode (struct ehci_hcd *ehci) @@ -212,7 +215,7 @@ static int ehci_halt (struct ehci_hcd *ehci) spin_unlock_irq(&ehci->lock); synchronize_irq(ehci_to_hcd(ehci)->irq); - return handshake(ehci, &ehci->regs->status, + return ehci_handshake(ehci, &ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); } @@ -251,7 +254,7 @@ static int ehci_reset (struct ehci_hcd *ehci) ehci_writel(ehci, command, &ehci->regs->command); ehci->rh_state = EHCI_RH_HALTED; ehci->next_statechange = jiffies; - retval = handshake (ehci, &ehci->regs->command, + retval = ehci_handshake(ehci, &ehci->regs->command, CMD_RESET, 0, 250 * 1000); if (ehci->has_hostpc) { @@ -286,7 +289,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /* wait for any schedule enables/disables to take effect */ temp = (ehci->command << 10) & (STS_ASS | STS_PSS); - handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); + ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, + 16 * 125); /* then disable anything that's still active */ spin_lock_irq(&ehci->lock); @@ -295,13 +299,15 @@ static void ehci_quiesce (struct ehci_hcd *ehci) spin_unlock_irq(&ehci->lock); /* hardware can take 16 microframes to turn off ... */ - handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); + ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, + 16 * 125); } /*-------------------------------------------------------------------------*/ static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -436,14 +442,6 @@ static void ehci_stop (struct usb_hcd *hcd) if (ehci->amd_pll_fix == 1) usb_amd_dev_put(); -#ifdef EHCI_STATS - ehci_dbg(ehci, "irq normal %ld err %ld iaa %ld (lost %ld)\n", - ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, - ehci->stats.lost_iaa); - ehci_dbg (ehci, "complete %ld unlink %ld\n", - ehci->stats.complete, ehci->stats.unlink); -#endif - dbg_status (ehci, "ehci_stop completed", ehci_readl(ehci, &ehci->regs->status)); } @@ -481,9 +479,14 @@ static int ehci_init(struct usb_hcd *hcd) * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; + INIT_LIST_HEAD(&ehci->async_unlink); + INIT_LIST_HEAD(&ehci->async_idle); + INIT_LIST_HEAD(&ehci->intr_unlink_wait); + INIT_LIST_HEAD(&ehci->intr_unlink); INIT_LIST_HEAD(&ehci->intr_qh_list); INIT_LIST_HEAD(&ehci->cached_itd_list); INIT_LIST_HEAD(&ehci->cached_sitd_list); + INIT_LIST_HEAD(&ehci->tt_list); if (HCC_PGM_FRAMELISTLEN(hcc_params)) { /* periodic schedule size can be smaller than default */ @@ -669,9 +672,6 @@ int ehci_setup(struct usb_hcd *hcd) if (retval) return retval; - if (ehci_is_TDI(ehci)) - tdi_reset(ehci); - ehci_reset(ehci); return 0; @@ -685,8 +685,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 status, masked_status, pcd_status = 0, cmd; int bh; + unsigned long flags; - spin_lock (&ehci->lock); + /* + * For threadirqs option we use spin_lock_irqsave() variant to prevent + * deadlock with ehci hrtimer callback, because hrtimer callbacks run + * in interrupt context even when threadirqs is specified. We can go + * back to spin_lock() variant when hrtimer callbacks become threaded. + */ + spin_lock_irqsave(&ehci->lock, flags); status = ehci_readl(ehci, &ehci->regs->status); @@ -704,7 +711,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* Shared IRQ? */ if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { - spin_unlock(&ehci->lock); + spin_unlock_irqrestore(&ehci->lock, flags); return IRQ_NONE; } @@ -713,13 +720,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) cmd = ehci_readl(ehci, &ehci->regs->command); bh = 0; -#ifdef VERBOSE_DEBUG - /* unrequested/ignored: Frame List Rollover */ - dbg_status (ehci, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - /* normal [4.15.1.2] or error [4.15.1.1] completion */ if (likely ((status & (STS_INT|STS_ERR)) != 0)) { if (likely ((status & STS_ERR) == 0)) @@ -748,17 +748,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* guard against (alleged) silicon errata */ if (cmd & CMD_IAAD) ehci_dbg(ehci, "IAA with IAAD still set?\n"); - if (ehci->async_iaa) { + if (ehci->iaa_in_progress) COUNT(ehci->stats.iaa); - end_unlink_async(ehci); - } else - ehci_dbg(ehci, "IAA with nothing unlinked?\n"); + end_unlink_async(ehci); } /* remote wakeup [4.3.1] */ if (status & STS_PCD) { unsigned i = HCS_N_PORTS (ehci->hcs_params); - u32 ppcd = 0; + u32 ppcd = ~0; /* kick root hub later */ pcd_status = status; @@ -775,7 +773,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) int pstatus; /* leverage per-port change bits feature */ - if (ehci->has_ppcd && !(ppcd & (1 << i))) + if (!(ppcd & (1 << i))) continue; pstatus = ehci_readl(ehci, &ehci->regs->port_status[i]); @@ -824,7 +822,7 @@ dead: if (bh) ehci_work (ehci); - spin_unlock (&ehci->lock); + spin_unlock_irqrestore(&ehci->lock, flags); if (pcd_status) usb_hcd_poll_rh_status(hcd); return IRQ_HANDLED; @@ -897,17 +895,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) if (rc) goto done; - switch (usb_pipetype (urb->pipe)) { - // case PIPE_CONTROL: - // case PIPE_BULK: - default: + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { + /* + * We don't expedite dequeue for isochronous URBs. + * Just wait until they complete normally or their + * time slot expires. + */ + } else { qh = (struct ehci_qh *) urb->hcpriv; - if (!qh) - break; + qh->exception = 1; switch (qh->qh_state) { case QH_STATE_LINKED: + if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) + start_unlink_intr(ehci, qh); + else + start_unlink_async(ehci, qh); + break; case QH_STATE_COMPLETING: - start_unlink_async(ehci, qh); + qh->dequeue_during_giveback = 1; break; case QH_STATE_UNLINK: case QH_STATE_UNLINK_WAIT: @@ -918,33 +923,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) qh_completions(ehci, qh); break; } - break; - - case PIPE_INTERRUPT: - qh = (struct ehci_qh *) urb->hcpriv; - if (!qh) - break; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - start_unlink_intr(ehci, qh); - break; - case QH_STATE_IDLE: - qh_completions (ehci, qh); - break; - default: - ehci_dbg (ehci, "bogus qh %p state %d\n", - qh, qh->qh_state); - goto done; - } - break; - - case PIPE_ISOCHRONOUS: - // itd or sitd ... - - // wait till next completion, do it then. - // completion irqs can wait up to 1024 msec, - break; } done: spin_unlock_irqrestore (&ehci->lock, flags); @@ -960,7 +938,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); unsigned long flags; - struct ehci_qh *qh, *tmp; + struct ehci_qh *qh; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ @@ -981,25 +959,23 @@ rescan: goto idle_timeout; /* BUG_ON(!list_empty(&stream->free_list)); */ + reserve_release_iso_bandwidth(ehci, stream, -1); kfree(stream); goto done; } + qh->exception = 1; if (ehci->rh_state < EHCI_RH_RUNNING) qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - for (tmp = ehci->async->qh_next.qh; - tmp && tmp != qh; - tmp = tmp->qh_next.qh) - continue; - /* periodic qh self-unlinks on empty, and a COMPLETING qh - * may already be unlinked. - */ - if (tmp) + WARN_ON(!list_empty(&qh->qtd_list)); + if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT) start_unlink_async(ehci, qh); + else + start_unlink_intr(ehci, qh); /* FALL THROUGH */ + case QH_STATE_COMPLETING: /* already in unlinking */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: idle_timeout: @@ -1010,6 +986,8 @@ idle_timeout: if (qh->clearing_tt) goto idle_timeout; if (list_empty (&qh->qtd_list)) { + if (qh->ps.bw_uperiod) + reserve_release_intr_bandwidth(ehci, qh, -1); qh_destroy(ehci, qh); break; } @@ -1050,16 +1028,15 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) * the toggle bit in the QH. */ if (qh) { - usb_settoggle(qh->dev, epnum, is_out, 0); if (!list_empty(&qh->qtd_list)) { WARN_ONCE(1, "clear_halt for a busy endpoint\n"); - } else if (qh->qh_state == QH_STATE_LINKED || - qh->qh_state == QH_STATE_COMPLETING) { - + } else { /* The toggle value in the QH can't be updated * while the QH is active. Unlink it now; * re-linking will call qh_refresh(). */ + usb_settoggle(qh->ps.udev, epnum, is_out, 0); + qh->exception = 1; if (eptype == USB_ENDPOINT_XFER_BULK) start_unlink_async(ehci, qh); else @@ -1077,6 +1054,19 @@ static int ehci_get_frame (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ +/* Device addition and removal */ + +static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + spin_lock_irq(&ehci->lock); + drop_tt(udev); + spin_unlock_irq(&ehci->lock); +} + +/*-------------------------------------------------------------------------*/ + #ifdef CONFIG_PM /* suspend/resume, section 4.3 */ @@ -1104,6 +1094,14 @@ int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irq(&ehci->lock); + synchronize_irq(hcd->irq); + + /* Check for race with a wakeup request */ + if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) { + ehci_resume(hcd, false); + return -EBUSY; + } + return 0; } EXPORT_SYMBOL_GPL(ehci_suspend); @@ -1187,7 +1185,7 @@ static const struct hc_driver ehci_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, + .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, /* * basic lifecycle operations @@ -1220,6 +1218,11 @@ static const struct hc_driver ehci_hc_driver = { .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, + + /* + * device support + */ + .free_dev = ehci_remove_device, }; void ehci_init_driver(struct hc_driver *drv, @@ -1252,11 +1255,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_sh_driver #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define PLATFORM_DRIVER ehci_hcd_omap_driver -#endif - #ifdef CONFIG_PPC_PS3 #include "ehci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver @@ -1272,41 +1270,11 @@ MODULE_LICENSE ("GPL"); #define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver #endif -#ifdef CONFIG_PLAT_ORION -#include "ehci-orion.c" -#define PLATFORM_DRIVER ehci_orion_driver -#endif - -#ifdef CONFIG_USB_W90X900_EHCI -#include "ehci-w90x900.c" -#define PLATFORM_DRIVER ehci_hcd_w90x900_driver -#endif - -#ifdef CONFIG_ARCH_AT91 -#include "ehci-atmel.c" -#define PLATFORM_DRIVER ehci_atmel_driver -#endif - #ifdef CONFIG_USB_OCTEON_EHCI #include "ehci-octeon.c" #define PLATFORM_DRIVER ehci_octeon_driver #endif -#ifdef CONFIG_ARCH_VT8500 -#include "ehci-vt8500.c" -#define PLATFORM_DRIVER vt8500_ehci_driver -#endif - -#ifdef CONFIG_PLAT_SPEAR -#include "ehci-spear.c" -#define PLATFORM_DRIVER spear_ehci_hcd_driver -#endif - -#ifdef CONFIG_USB_EHCI_MSM -#include "ehci-msm.c" -#define PLATFORM_DRIVER ehci_msm_driver -#endif - #ifdef CONFIG_TILE_USB #include "ehci-tilegx.c" #define PLATFORM_DRIVER ehci_hcd_tilegx_driver @@ -1317,16 +1285,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_msp_driver #endif -#ifdef CONFIG_USB_EHCI_TEGRA -#include "ehci-tegra.c" -#define PLATFORM_DRIVER tegra_ehci_driver -#endif - -#ifdef CONFIG_USB_EHCI_S5P -#include "ehci-s5p.c" -#define PLATFORM_DRIVER s5p_ehci_driver -#endif - #ifdef CONFIG_SPARC_LEON #include "ehci-grlib.c" #define PLATFORM_DRIVER ehci_grlib_driver @@ -1342,17 +1300,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_sead3_driver #endif -#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ - !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ - !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ - !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ - !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && \ - !defined(OF_PLATFORM_DRIVER) && \ - !defined(XILINX_OF_PLATFORM_DRIVER) -#error "missing bus glue for ehci-hcd" -#endif - static int __init ehci_hcd_init(void) { int retval = 0; @@ -1372,7 +1319,7 @@ static int __init ehci_hcd_init(void) sizeof(struct ehci_qh), sizeof(struct ehci_qtd), sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); -#ifdef DEBUG +#ifdef CONFIG_DYNAMIC_DEBUG ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); if (!ehci_debug_root) { retval = -ENOENT; @@ -1421,7 +1368,7 @@ clean2: platform_driver_unregister(&PLATFORM_DRIVER); clean0: #endif -#ifdef DEBUG +#ifdef CONFIG_DYNAMIC_DEBUG debugfs_remove(ehci_debug_root); ehci_debug_root = NULL; err_debug: @@ -1445,7 +1392,7 @@ static void __exit ehci_hcd_cleanup(void) #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif -#ifdef DEBUG +#ifdef CONFIG_DYNAMIC_DEBUG debugfs_remove(ehci_debug_root); #endif clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); |
