diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-atmel.c | 29 | ||||
-rw-r--r-- | drivers/usb/host/ehci-core.h | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 61 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 12 | ||||
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 33 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 29 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 105 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 222 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 99 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 34 |
14 files changed, 364 insertions, 291 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 891523c4d2..d38b4dcac4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config USB_EHCI bool "EHCI driver" depends on HAS_DMA diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e7a6cf213e..e55dff4580 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_USB_EHCI) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index c3f8ab7ad5..f176babfa7 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -1,16 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * (C) Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> @@ -18,9 +8,9 @@ #include <linux/err.h> #include <driver.h> #include <init.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> -#include <usb/ehci.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> +#include <linux/usb/ehci.h> #include <errno.h> #include <io.h> @@ -28,7 +18,7 @@ struct atmel_ehci_priv { struct ehci_host *ehci; - struct device_d *dev; + struct device *dev; struct clk *iclk; struct clk *uclk; }; @@ -57,7 +47,7 @@ static void atmel_stop_clock(struct atmel_ehci_priv *atehci) clk_disable(atehci->uclk); } -static int atmel_ehci_probe(struct device_d *dev) +static int atmel_ehci_probe(struct device *dev) { int ret; struct resource *iores; @@ -66,7 +56,7 @@ static int atmel_ehci_probe(struct device_d *dev) const char *uclk_name; struct ehci_host *ehci; - uclk_name = (dev->device_node) ? "usb_clk" : "uhpck"; + uclk_name = (dev->of_node) ? "usb_clk" : "uhpck"; atehci = xzalloc(sizeof(*atehci)); atehci->dev = dev; @@ -107,7 +97,7 @@ static int atmel_ehci_probe(struct device_d *dev) return 0; } -static void atmel_ehci_remove(struct device_d *dev) +static void atmel_ehci_remove(struct device *dev) { struct atmel_ehci_priv *atehci = dev->priv; @@ -123,8 +113,9 @@ static const struct of_device_id atmel_ehci_dt_ids[] = { { .compatible = "atmel,at91sam9g45-ehci" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids); -static struct driver_d atmel_ehci_driver = { +static struct driver atmel_ehci_driver = { .name = "atmel-ehci", .probe = atmel_ehci_probe, .remove = atmel_ehci_remove, diff --git a/drivers/usb/host/ehci-core.h b/drivers/usb/host/ehci-core.h index 584dd541ad..8f43783f7e 100644 --- a/drivers/usb/host/ehci-core.h +++ b/drivers/usb/host/ehci-core.h @@ -1,18 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Excito Elektronik i Skåne AB * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef USB_EHCI_CORE_H diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 30a16103eb..7ae3a285a0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1,26 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-only /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Excito Elektronik i Skåne AB * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> * * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ /*#define DEBUG */ #include <common.h> #include <dma.h> #include <asm/byteorder.h> -#include <usb/usb.h> +#include <linux/usb/usb.h> #include <io.h> #include <malloc.h> #include <driver.h> @@ -29,7 +19,7 @@ #include <clock.h> #include <errno.h> #include <of.h> -#include <usb/ehci.h> +#include <linux/usb/ehci.h> #include <linux/err.h> #include <linux/sizes.h> #include <linux/clk.h> @@ -39,7 +29,7 @@ struct ehci_host { int rootdev; - struct device_d *dev; + struct device *dev; struct ehci_hccr *hccr; struct ehci_hcor *hcor; struct usb_host host; @@ -252,7 +242,7 @@ static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz) return 0; } -static int ehci_prepare_qtd(struct device_d *dev, +static int ehci_prepare_qtd(struct device *dev, struct qTD *td, uint32_t token, void *buffer, size_t length, dma_addr_t *buffer_dma, @@ -520,7 +510,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, } #if defined(CONFIG_MACH_EFIKA_MX_SMARTBOOK) && defined(CONFIG_USB_ULPI) -#include <usb/ulpi.h> +#include <linux/usb/ulpi.h> /* * Add support for setting CHRGVBUS to workaround a hardware bug on efika mx/sb * boards. @@ -1351,7 +1341,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return result; } -struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) +struct ehci_host *ehci_register(struct device *dev, struct ehci_data *data) { struct usb_host *host; struct ehci_host *ehci; @@ -1408,12 +1398,12 @@ void ehci_unregister(struct ehci_host *ehci) free(ehci); } -static int ehci_probe(struct device_d *dev) +static int ehci_probe(struct device *dev) { struct resource *iores; struct ehci_data data = {}; struct ehci_platform_data *pdata = dev->platform_data; - struct device_node *dn = dev->device_node; + struct device_node *dn = dev->of_node; struct ehci_host *ehci; struct clk_bulk_data *clks; int num_clocks, ret; @@ -1431,20 +1421,6 @@ static int ehci_probe(struct device_d *dev) */ data.flags = EHCI_HAS_TT; - iores = dev_request_mem_resource(dev, 0); - if (IS_ERR(iores)) - return PTR_ERR(iores); - data.hccr = IOMEM(iores->start); - - if (dev->num_resources > 1) { - iores = dev_request_mem_resource(dev, 1); - if (IS_ERR(iores)) - return PTR_ERR(iores); - data.hcor = IOMEM(iores->start); - } - else - data.hcor = NULL; - usb2_generic_phy = phy_optional_get(dev, "usb"); if (IS_ERR(usb2_generic_phy)) return PTR_ERR(usb2_generic_phy); @@ -1466,6 +1442,20 @@ static int ehci_probe(struct device_d *dev) if (ret) return ret; + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + data.hccr = IOMEM(iores->start); + + if (dev->num_resources > 1) { + iores = dev_request_mem_resource(dev, 1); + if (IS_ERR(iores)) + return PTR_ERR(iores); + data.hcor = IOMEM(iores->start); + } + else + data.hcor = NULL; + ehci = ehci_register(dev, &data); if (IS_ERR(ehci)) return PTR_ERR(ehci); @@ -1475,7 +1465,7 @@ static int ehci_probe(struct device_d *dev) return 0; } -static void ehci_remove(struct device_d *dev) +static void ehci_remove(struct device *dev) { struct ehci_host *ehci = dev->priv; @@ -1489,8 +1479,9 @@ static __maybe_unused struct of_device_id ehci_platform_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, ehci_platform_dt_ids); -static struct driver_d ehci_driver = { +static struct driver ehci_driver = { .name = "ehci", .probe = ehci_probe, .remove = ehci_remove, diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index fc5a54f671..e364796a1a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de> - * - * This file is released under the GPLv2 - * */ /* @@ -12,16 +10,16 @@ /*-------------------------------------------------------------------------*/ #include <mfd/twl4030.h> -#include <usb/twl4030.h> -#include <mach/ehci.h> +#include <linux/usb/twl4030.h> +#include <mach/omap/ehci.h> #include <common.h> #include <io.h> #include <clock.h> #include <gpio.h> -#include <mach/omap3-silicon.h> -#include <mach/omap3-clock.h> -#include <mach/cm-regbits-34xx.h> -#include <mach/sys_info.h> +#include <mach/omap/omap3-silicon.h> +#include <mach/omap/omap3-clock.h> +#include <mach/omap/cm-regbits-34xx.h> +#include <mach/omap/sys_info.h> void omap_usb_utmi_init(struct omap_hcd *omap, u8 tll_channel_mask) { diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 4b9092d1fe..49196bfc7d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -1,18 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef USB_EHCI_H diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 05ed2876c6..867c0977be 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -1,30 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * (C) Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> #include <linux/clk.h> #include <driver.h> #include <init.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> #include <errno.h> #include <gpio.h> #include <of_gpio.h> #include <io.h> -#include <mach/board.h> +#include <mach/at91/board.h> #include "ohci.h" @@ -33,7 +23,7 @@ struct ohci_at91_priv { - struct device_d *dev; + struct device *dev; struct clk *iclk; struct clk *fclk; struct ohci_regs __iomem *regs; @@ -64,13 +54,13 @@ static void at91_stop_clock(struct ohci_at91_priv *ohci_at91) clk_disable(ohci_at91->iclk); } -static int at91_ohci_probe_dt(struct device_d *dev) +static int at91_ohci_probe_dt(struct device *dev) { u32 ports; int i, ret, gpio; enum of_gpio_flags flags; struct at91_usbh_data *pdata; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; pdata = xzalloc(sizeof(*pdata)); dev->platform_data = pdata; @@ -117,7 +107,7 @@ static int at91_ohci_probe_dt(struct device_d *dev) return 0; } -static int at91_ohci_probe(struct device_d *dev) +static int at91_ohci_probe(struct device *dev) { int ret; struct resource *io; @@ -126,7 +116,7 @@ static int at91_ohci_probe(struct device_d *dev) dev->priv = ohci_at91; ohci_at91->dev = dev; - if (dev->device_node) { + if (dev->of_node) { ret = at91_ohci_probe_dt(dev); if (ret < 0) return ret; @@ -169,7 +159,7 @@ static int at91_ohci_probe(struct device_d *dev) return 0; } -static void at91_ohci_remove(struct device_d *dev) +static void at91_ohci_remove(struct device *dev) { struct at91_usbh_data *pdata = dev->platform_data; struct ohci_at91_priv *ohci_at91 = dev->priv; @@ -204,8 +194,9 @@ static const struct of_device_id at91_ohci_dt_ids[] = { { .compatible = "atmel,at91rm9200-ohci" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); -static struct driver_d at91_ohci_driver = { +static struct driver at91_ohci_driver = { .name = "at91_ohci", .probe = at91_ohci_probe, .remove = at91_ohci_remove, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a28c48b4c8..ae4c34e818 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. * @@ -16,18 +17,6 @@ * * Modified for the MP2USB by (C) Copyright 2005 Eric Benard * ebenard@eukrea.com - based on s3c24x0's driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * */ /* * IMPORTANT NOTES @@ -38,12 +27,11 @@ * to activate workaround for bug #41 or this driver will NOT work! */ #include <common.h> -#include <dma.h> #include <clock.h> #include <dma.h> #include <malloc.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> #include <init.h> #include <errno.h> #include <linux/err.h> @@ -854,7 +842,8 @@ static void td_fill(struct ohci *ohci, unsigned int info, td->hwNextTD = virt_to_phys((void *)m32_swap((unsigned long)td_pt)); - dma_sync_single_for_device((unsigned long)data, len, DMA_BIDIRECTIONAL); + dma_sync_single_for_device(ohci->host.hw_dev, (unsigned long)data, + len, DMA_BIDIRECTIONAL); /* append to queue */ td->ed->hwTailP = td->hwNextTD; @@ -1090,7 +1079,7 @@ static int dl_done_list(struct ohci *ohci) unsigned long ptdphys = virt_to_phys(ptd); struct td *td_list; - dma_sync_single_for_device((unsigned long)ptdphys, + dma_sync_single_for_device(ohci->host.hw_dev, (unsigned long)ptdphys, sizeof(struct td) * NUM_TD, DMA_BIDIRECTIONAL); td_list = dl_reverse_done_list(ohci); @@ -1527,7 +1516,7 @@ static int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *b dev->status = stat; dev->act_len = urb->actual_length; - dma_sync_single_for_cpu((unsigned long)buffer, transfer_len, + dma_sync_single_for_cpu(host->hw_dev, (unsigned long)buffer, transfer_len, DMA_BIDIRECTIONAL); pkt_print(urb, dev, pipe, buffer, transfer_len, @@ -1787,7 +1776,7 @@ static int ohci_init(struct usb_host *host) return 0; } -static int ohci_probe(struct device_d *dev) +static int ohci_probe(struct device *dev) { struct resource *iores; struct usb_host *host; @@ -1822,7 +1811,7 @@ static int ohci_probe(struct device_d *dev) return 0; } -static struct driver_d ohci_driver = { +static struct driver ohci_driver = { .name = "ohci", .probe = ohci_probe, }; diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 9c9b8375ce..7d70bcb719 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * URB OHCI HCD (Host Controller Driver) for USB. * diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f66dadef12..e962bfde3f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -20,8 +20,8 @@ #include <io.h> #include <linux/err.h> #include <linux/sizes.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" @@ -82,11 +82,11 @@ static void xhci_free(struct xhci_ctrl *ctrl, void *ptr) * @param size size of memory to be allocated * @return allocates the memory and returns the aligned pointer */ -static void *xhci_malloc(struct xhci_ctrl *ctrl, unsigned int size) +static void *xhci_malloc(struct xhci_ctrl *ctrl, unsigned int size, dma_addr_t *dma_addr) { void *ptr; - ptr = dma_alloc_coherent(size, DMA_ADDRESS_BROKEN); + ptr = dma_alloc_coherent(size, dma_addr); if (!ptr) return NULL; @@ -145,7 +145,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) ctrl->dcbaa->dev_context_ptrs[0] = 0; - xhci_free(ctrl, (void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); + xhci_free(ctrl, ctrl->scratchpad->scratchpad); xhci_free(ctrl, ctrl->scratchpad->sp_array); free(ctrl->scratchpad); ctrl->scratchpad = NULL; @@ -234,14 +234,13 @@ static void xhci_link_segments(struct xhci_segment *prev, struct xhci_segment *next, bool link_trbs) { u32 val; - u64 val_64 = 0; if (!prev || !next) return; prev->next = next; if (link_trbs) { - val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; + prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = + cpu_to_le64(next->dma); /* * Set the last TRB in the segment to @@ -249,8 +248,7 @@ static void xhci_link_segments(struct xhci_segment *prev, */ val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); val &= ~TRB_TYPE_BITMASK; - val |= (TRB_LINK << TRB_TYPE_SHIFT); - + val |= TRB_TYPE(TRB_LINK); prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); } } @@ -295,7 +293,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_ctrl *ctrl) seg = xzalloc(sizeof(*seg)); - seg->trbs = xhci_malloc(ctrl, SEGMENT_SIZE); + seg->trbs = xhci_malloc(ctrl, SEGMENT_SIZE, &seg->dma); return seg; } @@ -365,6 +363,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) struct xhci_hccr *hccr = ctrl->hccr; struct xhci_hcor *hcor = ctrl->hcor; struct xhci_scratchpad *scratchpad; + dma_addr_t val_64; int num_sp; uint32_t page_size; void *buf; @@ -379,11 +378,11 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) goto fail_sp; ctrl->scratchpad = scratchpad; - scratchpad->sp_array = xhci_malloc(ctrl, num_sp * sizeof(u64)); + scratchpad->sp_array = xhci_malloc(ctrl, num_sp * sizeof(u64), &val_64); if (!scratchpad->sp_array) goto fail_sp2; - ctrl->dcbaa->dev_context_ptrs[0] = - cpu_to_le64((uintptr_t)scratchpad->sp_array); + + ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0], sizeof(ctrl->dcbaa->dev_context_ptrs[0])); @@ -397,17 +396,21 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) BUG_ON(i == 16); page_size = 1 << (i + 12); - buf = xhci_malloc(ctrl, num_sp * page_size); + buf = xhci_malloc(ctrl, num_sp * page_size, &val_64); if (!buf) goto fail_sp3; xhci_flush_cache((uintptr_t)buf, num_sp * page_size); + scratchpad->scratchpad = buf; for (i = 0; i < num_sp; i++) { - uintptr_t ptr = (uintptr_t)buf + i * page_size; - scratchpad->sp_array[i] = cpu_to_le64(ptr); + scratchpad->sp_array[i] = cpu_to_le64(val_64); + val_64 += page_size; } + xhci_flush_cache((uintptr_t)scratchpad->sp_array, + sizeof(u64) * num_sp); + return 0; fail_sp3: @@ -438,11 +441,11 @@ static struct xhci_container_ctx BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); ctx->type = type; ctx->size = (MAX_EP_CTX_NUM + 1) * - CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); + CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)); if (type == XHCI_CTX_TYPE_INPUT) - ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); + ctx->size += CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)); - ctx->bytes = xhci_malloc(ctrl, ctx->size); + ctx->bytes = xhci_malloc(ctrl, ctx->size, &ctx->dma); return ctx; } @@ -464,8 +467,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) return -EEXIST; } - ctrl->devs[slot_id] = (struct xhci_virt_device *) - malloc(sizeof(struct xhci_virt_device)); + ctrl->devs[slot_id] = malloc(sizeof(struct xhci_virt_device)); if (!ctrl->devs[slot_id]) { dev_err(ctrl->dev, "Failed to allocate virtual device\n"); @@ -494,10 +496,10 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) /* Allocate endpoint 0 ring */ virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true); - byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); + byte_64 = virt_dev->out_ctx->dma; /* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; + ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], sizeof(__le64)); @@ -516,29 +518,27 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, struct xhci_hcor *hcor) { + dma_addr_t dma; uint64_t val_64; uint64_t trb_64; uint32_t val; - unsigned long deq; + uint64_t deq; int i; struct xhci_segment *seg; /* DCBAA initialization */ - ctrl->dcbaa = xhci_malloc(ctrl, sizeof(*ctrl->dcbaa)); - if (!ctrl->dcbaa) { - dev_err(ctrl->dev, "unable to allocate DCBA\n"); - return -ENOMEM; - } + ctrl->dcbaa = xhci_malloc(ctrl, sizeof(struct xhci_device_context_array), + &dma); + ctrl->dcbaa->dma = dma; - val_64 = (uintptr_t)ctrl->dcbaa; /* Set the pointer in DCBAA register */ - xhci_writeq(&hcor->or_dcbaap, val_64); + xhci_writeq(&hcor->or_dcbaap, dma); /* Command ring control pointer register initialization */ ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true); /* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; + trb_64 = ctrl->cmd_ring->first_seg->dma; val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | @@ -560,8 +560,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* Event ring does not maintain link TRB */ ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false); - ctrl->erst.entries = - xhci_malloc(ctrl, sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); + ctrl->erst.entries = xhci_malloc(ctrl, sizeof(struct xhci_erst_entry) * + ERST_NUM_SEGS, &ctrl->erst.erst_dma_addr); ctrl->erst.num_entries = ERST_NUM_SEGS; @@ -570,9 +570,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, val++) { struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; - xhci_writeq(&entry->seg_addr, trb_64); + trb_64 = seg->dma; + entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next; @@ -580,7 +579,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_flush_cache((uintptr_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - deq = (unsigned long)ctrl->event_ring->dequeue; + deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg, + ctrl->event_ring->dequeue); /* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, @@ -595,7 +595,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; - val_64 |= ((uintptr_t)(ctrl->erst.entries) & ~ERST_PTR_MASK); + val_64 |= ctrl->erst.erst_dma_addr & ~ERST_PTR_MASK; xhci_writeq(&ctrl->ir_set->erst_base, val_64); @@ -645,7 +645,7 @@ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, return (struct xhci_slot_ctx *)ctx->bytes; return (struct xhci_slot_ctx *) - (ctx->bytes + CTX_SIZE(readl(&ctrl->hccr->cr_hccparams))); + (ctx->bytes + CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams))); } /** @@ -667,7 +667,7 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, return (struct xhci_ep_ctx *) (ctx->bytes + - (ep_index * CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)))); + (ep_index * CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)))); } /** @@ -776,7 +776,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, dev_dbg(&udev->dev, "route string 0x%x\n", route); - slot_ctx->dev_info |= route; + slot_ctx->dev_info |= cpu_to_le32(route); switch (speed) { case USB_SPEED_SUPER: @@ -824,25 +824,22 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, /* Step 4 - ring already allocated */ /* Step 5 */ - ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); + ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); dev_dbg(&udev->dev, "SPEED = %d\n", speed); switch (speed) { case USB_SPEED_SUPER: - ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512)); dev_dbg(&udev->dev, "Setting Packet size = 512bytes\n"); break; case USB_SPEED_HIGH: /* USB core guesses at a 64-byte max packet first for FS devices */ case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64)); dev_dbg(&udev->dev, "Setting Packet size = 64bytes\n"); break; case USB_SPEED_LOW: - ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8)); dev_dbg(&udev->dev, "Setting Packet size = 8bytes\n"); break; default: @@ -851,11 +848,9 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ - ep0_ctx->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); - trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; + trb_64 = virt_dev->eps[0].ring->first_seg->dma; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 61b1b55a27..691d9c7463 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -19,12 +19,30 @@ #include <io.h> #include <linux/err.h> #include <linux/sizes.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" +/* + * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA + * address of the TRB. + */ +dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, + union xhci_trb *trb) +{ + unsigned long segment_offset; + + BUG_ON(!seg || !trb || trb < seg->trbs); + + /* offset in TRBs */ + segment_offset = trb - seg->trbs; + BUG_ON(segment_offset >= TRBS_PER_SEGMENT); + + return seg->dma + (segment_offset * sizeof(*trb)); +} + /** * Is this TRB a link TRB or was the last TRB the last TRB in this event ring * segment? I.e. would the updated event TRB pointer step off the end of the @@ -181,12 +199,11 @@ static void inc_deq(struct xhci_ctrl *ctrl, struct xhci_ring *ring) * @param trb_fields pointer to trb field array containing TRB contents * @return pointer to the enqueued trb */ -static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - bool more_trbs_coming, - unsigned int *trb_fields) +static dma_addr_t queue_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring, + bool more_trbs_coming, unsigned int *trb_fields) { struct xhci_generic_trb *trb; + dma_addr_t addr; int i; trb = &ring->enqueue->generic; @@ -196,9 +213,11 @@ static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, xhci_flush_cache((uintptr_t)trb, sizeof(struct xhci_generic_trb)); + addr = xhci_trb_virt_to_dma(ring->enq_seg, (union xhci_trb *)trb); + inc_enq(ctrl, ring, more_trbs_coming); - return trb; + return addr; } /** @@ -273,16 +292,15 @@ static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring, * @param cmd Command type to enqueue * @return none */ -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, +void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd) { u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); - fields[0] = lower_32_bits(val_64); - fields[1] = upper_32_bits(val_64); + fields[0] = lower_32_bits(addr); + fields[1] = upper_32_bits(addr); fields[2] = 0; fields[3] = TRB_TYPE(cmd) | SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; @@ -396,12 +414,15 @@ static void giveback_first_trb(struct usb_device *udev, int ep_index, */ void xhci_acknowledge_event(struct xhci_ctrl *ctrl) { + dma_addr_t deq; + /* Advance our dequeue pointer to the next event */ inc_deq(ctrl, ctrl->event_ring); /* Inform the hardware */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); + deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg, + ctrl->event_ring->dequeue); + xhci_writeq(&ctrl->ir_set->erst_dequeue, deq | ERST_EHB); } /** @@ -436,7 +457,8 @@ static int event_ready(struct xhci_ctrl *ctrl) * @param expected TRB type expected from Event TRB * @return pointer to event trb */ -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + unsigned int timeout_ms) { trb_type type; uint64_t start = get_time_ns(); @@ -448,7 +470,8 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) continue; type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); - if (type == expected) + if (type == expected || + (expected == TRB_NONE && type != TRB_PORT_STATUS)) return event; if (type == TRB_PORT_STATUS) @@ -461,7 +484,7 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS); else - dev_err(ctrl->dev, "Unexpected XHCI event TRB, skipping... " + dev_dbg(ctrl->dev, "Unexpected XHCI event TRB, skipping... " "(%08x %08x %08x %08x)\n", le32_to_cpu(event->generic.field[0]), le32_to_cpu(event->generic.field[1]), @@ -469,13 +492,50 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) le32_to_cpu(event->generic.field[3])); xhci_acknowledge_event(ctrl); - } while (!is_timeout_non_interruptible(start, 5 * SECOND)); + } while (!is_timeout_non_interruptible(start, timeout_ms * MSECOND)); if (expected == TRB_TRANSFER) return NULL; - dev_err(ctrl->dev, "XHCI timeout on event type %d... cannot recover.\n", expected); - BUG(); + dev_warn(ctrl->dev, "XHCI timeout on event type %d...\n", expected); + + return NULL; +} + +/* + * Send reset endpoint command for given endpoint. This recovers from a + * halted endpoint (e.g. due to a stall error). + */ +static void reset_ep(struct usb_device *udev, int ep_index, unsigned int timeout_ms) +{ + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; + union xhci_trb *event; + u64 addr; + u32 field; + + dev_info(&udev->dev, "Resetting EP %d...\n", ep_index); + + xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_RESET_EP); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms); + if (!event) + return; + + field = le32_to_cpu(event->trans_event.flags); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); + xhci_acknowledge_event(ctrl); + + addr = xhci_trb_virt_to_dma(ring->enq_seg, + (void *)((uintptr_t)ring->enqueue | ring->cycle_state)); + xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms); + if (!event) + return; + + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) + != udev->slot_id || GET_COMP_CODE(le32_to_cpu( + event->event_cmd.status)) != COMP_SUCCESS); + xhci_acknowledge_event(ctrl); } /* @@ -491,27 +551,49 @@ static void abort_td(struct usb_device *udev, int ep_index) struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; union xhci_trb *event; + xhci_comp_code comp; + trb_type type; + dma_addr_t addr; u32 field; - xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); + xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_STOP_RING); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len - != COMP_STOP))); - xhci_acknowledge_event(ctrl); + event = xhci_wait_for_event(ctrl, TRB_NONE, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); + type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); + if (type == TRB_TRANSFER) { + field = le32_to_cpu(event->trans_event.flags); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); + BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); + BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len + != COMP_STOP))); + xhci_acknowledge_event(ctrl); + + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; + type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); + + } else { + dev_warn(ctrl->dev, "abort_td: Expected a TRB_TRANSFER TRB first\n"); + } + + comp = GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)); + BUG_ON(type != TRB_COMPLETION || + TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) + != udev->slot_id || (comp != COMP_SUCCESS && comp + != COMP_CTX_STATE)); xhci_acknowledge_event(ctrl); - xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue | - ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + addr = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue); + addr |= ring->cycle_state; + xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id || GET_COMP_CODE(le32_to_cpu( event->event_cmd.status)) != COMP_SUCCESS); @@ -557,7 +639,7 @@ static void record_transfer_result(struct usb_device *udev, * @return returns 0 if successful else -1 on failure */ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer) + int length, void *buffer, unsigned int timeout_ms) { int num_trbs = 0; struct xhci_generic_trb *start_trb; @@ -601,7 +683,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, memcpy(bounce, buffer, length); } - map = addr = dma_map_single(ctrl->dev, bounce, length, direction); + map = addr = dma_map_single(ctrl->host.hw_dev, bounce, length, direction); dev_dbg(&udev->dev, "pipe=0x%lx, buffer=%p, length=%d\n", pipe, buffer, length); @@ -614,6 +696,14 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); + /* + * If the endpoint was halted due to a prior error, resume it before + * the next transfer. It is the responsibility of the upper layer to + * have dealt with whatever caused the error. + */ + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED) + reset_ep(udev, ep_index, timeout_ms); + ring = virt_dev->eps[ep_index].ring; /* * How much data is (potentially) left before the 64KB boundary? @@ -646,8 +736,10 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, */ ret = prepare_ring(ctrl, ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - if (ret < 0) + if (ret < 0) { + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return ret; + } /* * Don't give the first TRB to the hardware (by toggling the cycle bit) @@ -667,6 +759,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, first_trb = true; + /* flush the buffer before use */ + xhci_flush_cache((uintptr_t)buffer, length); + /* Queue the first TRB, even if it's zero-length */ do { u32 remainder = 0; @@ -703,15 +798,14 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, maxpacketsize, num_trbs - 1); - length_field = ((trb_buff_len & TRB_LEN_MASK) | + length_field = (TRB_LEN(trb_buff_len) | remainder | - ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); + TRB_INTR_TARGET(0)); trb_fields[0] = lower_32_bits(addr); trb_fields[1] = upper_32_bits(addr); trb_fields[2] = length_field; - trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT); + trb_fields[3] = field | TRB_TYPE(TRB_NORMAL); queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); @@ -726,12 +820,13 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, giveback_first_trb(udev, ep_index, start_cycle, start_trb); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) { dev_dbg(&udev->dev, "XHCI bulk transfer timed out, aborting...\n"); abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ udev->act_len = 0; + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return -ETIMEDOUT; } field = le32_to_cpu(event->trans_event.flags); @@ -747,7 +842,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, record_transfer_result(udev, event, length); xhci_acknowledge_event(ctrl); - dma_unmap_single(ctrl->dev, map, length, direction); + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); if (usb_pipein(pipe)) memcpy(buffer, bounce, length); @@ -767,7 +862,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, */ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, struct devrequest *req, int length, - void *buffer) + void *buffer, unsigned int timeout_ms) { int ret; int start_cycle; @@ -846,7 +941,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* Queue setup TRB - see section 6.4.1.2.1 */ /* FIXME better way to translate setup_packet into two u32 fields? */ field = 0; - field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT); + field |= TRB_IDT | TRB_TYPE(TRB_SETUP); if (start_cycle == 0) field |= 0x1; @@ -854,9 +949,9 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) >= 0x100) { if (length > 0) { if (req->requesttype & USB_DIR_IN) - field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT); + field |= TRB_TX_TYPE(TRB_DATA_IN); else - field |= (TRB_DATA_OUT << TRB_TX_TYPE_SHIFT); + field |= TRB_TX_TYPE(TRB_DATA_OUT); } } @@ -872,8 +967,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, trb_fields[1] = le16_to_cpu(req->index) | le16_to_cpu(req->length) << 16; /* TRB_LEN | (TRB_INTR_TARGET) */ - trb_fields[2] = (8 | ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); + trb_fields[2] = (TRB_LEN(8) | TRB_INTR_TARGET(0)); /* Immediate data in pointer */ trb_fields[3] = field; queue_trb(ctrl, ep_ring, true, trb_fields); @@ -883,15 +977,15 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* If there's data, queue data TRBs */ /* Only set interrupt on short packet for IN endpoints */ if (usb_pipein(pipe)) - field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT); + field = TRB_ISP | TRB_TYPE(TRB_DATA); else - field = (TRB_DATA << TRB_TYPE_SHIFT); + field = TRB_TYPE(TRB_DATA); - length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) | + length_field = TRB_LEN(length) | xhci_td_remainder(length) | ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); dev_dbg(&udev->dev, "length_field = %d, length = %d," "xhci_td_remainder(length) = %d , TRB_INTR_TARGET(0) = %d\n", - length_field, (length & TRB_LEN_MASK), + length_field, TRB_LEN(length), xhci_td_remainder(length), 0); if (req->requesttype & USB_DIR_IN) @@ -902,13 +996,14 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (length > 0) { if (req->requesttype & USB_DIR_IN) field |= TRB_DIR_IN; - map = buf_64 = dma_map_single(ctrl->dev, buffer, length, direction); + map = buf_64 = dma_map_single(ctrl->host.hw_dev, buffer, length, direction); trb_fields[0] = lower_32_bits(buf_64); trb_fields[1] = upper_32_bits(buf_64); trb_fields[2] = length_field; trb_fields[3] = field | ep_ring->cycle_state; + xhci_flush_cache((uintptr_t)buffer, length); queue_trb(ctrl, ep_ring, true, trb_fields); } @@ -926,17 +1021,16 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, trb_fields[0] = 0; trb_fields[1] = 0; - trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); + trb_fields[2] = TRB_INTR_TARGET(0); /* Event on completion */ trb_fields[3] = field | TRB_IOC | - (TRB_STATUS << TRB_TYPE_SHIFT) | - ep_ring->cycle_state; + TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state; queue_trb(ctrl, ep_ring, false, trb_fields); giveback_first_trb(udev, ep_index, start_cycle, start_trb); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) goto abort; field = le32_to_cpu(event->trans_event.flags); @@ -954,12 +1048,17 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* Invalidate buffer to make it available to usb-core */ if (length > 0) - dma_unmap_single(ctrl->dev, map, length, direction); + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); + + if (udev->status == USB_ST_STALLED) { + reset_ep(udev, ep_index, timeout_ms); + return -EPIPE; + } if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)) == COMP_SHORT_TX) { /* Short data stage, clear up additional status stage event */ - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) goto abort; BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); @@ -974,5 +1073,6 @@ abort: abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; udev->act_len = 0; + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return -ETIMEDOUT; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index caab2400d8..e7b8344181 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -24,13 +24,13 @@ #include <init.h> #include <io.h> #include <linux/err.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" -static struct descriptor { +static const struct descriptor { struct usb_hub_descriptor hub; struct usb_device_descriptor device; struct usb_config_descriptor config; @@ -151,6 +151,8 @@ static int xhci_start(struct xhci_ctrl *ctrl) u32 temp; int ret; + dev_dbg(ctrl->dev, "Starting the controller\n"); + temp = xhci_readl(&hcor->or_usbcmd); temp |= (CMD_RUN); xhci_writel(&hcor->or_usbcmd, temp); @@ -441,9 +443,12 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) in_ctx = virt_dev->in_ctx; xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size); - xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0, + xhci_queue_command(ctrl, in_ctx->dma, udev->slot_id, 0, ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id); @@ -566,8 +571,7 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) | EP_INTERVAL(interval) | EP_MULT(mult)); - ep_ctx[ep_index]->ep_info2 = - cpu_to_le32(ep_type << EP_TYPE_SHIFT); + ep_ctx[ep_index]->ep_info2 = cpu_to_le32(EP_TYPE(ep_type)); ep_ctx[ep_index]->ep_info2 |= cpu_to_le32(MAX_PACKET (get_unaligned(&endpt_desc->wMaxPacketSize))); @@ -579,8 +583,8 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(MAX_BURST(max_burst) | ERROR_COUNT(err_count)); - trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; + trb_64 = xhci_trb_virt_to_dma(virt_dev->eps[ep_index].ring->enq_seg, + virt_dev->eps[ep_index].ring->enqueue); ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | virt_dev->eps[ep_index].ring->cycle_state); @@ -628,8 +632,12 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); ctrl_ctx->drop_flags = 0; - xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + xhci_queue_command(ctrl, virt_dev->in_ctx->dma, + slot_id, 0, TRB_ADDR_DEV); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id); switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { @@ -703,8 +711,11 @@ static int _xhci_alloc_device(struct usb_device *udev) return 0; } - xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + xhci_queue_command(ctrl, 0, 0, 0, TRB_ENABLE_SLOT); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)) != COMP_SUCCESS); @@ -764,8 +775,7 @@ int xhci_check_maxpacket(struct usb_device *udev) ctrl->devs[slot_id]->out_ctx, ep_index); in_ctx = ctrl->devs[slot_id]->in_ctx; ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - ep_ctx->ep_info2 &= cpu_to_le32(~((0xffff & MAX_PACKET_MASK) - << MAX_PACKET_SHIFT)); + ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET(MAX_PACKET_MASK)); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); /* @@ -860,7 +870,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, { uint8_t tmpbuf[4]; u16 typeReq; - void *srcptr = NULL; + const void *srcptr = NULL; int len, srclen; uint32_t reg; volatile uint32_t *status_reg; @@ -928,7 +938,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, case USB_DT_HUB: case USB_DT_SS_HUB: dev_dbg(&udev->dev, "USB_DT_HUB config\n"); - srcptr = &descriptor.hub; + srcptr = &ctrl->hub_desc; srclen = 0x8; break; default: @@ -1088,8 +1098,10 @@ unknown: static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, int interval) { - if (usb_pipetype(pipe) != PIPE_INTERRUPT) + if (usb_pipetype(pipe) != PIPE_INTERRUPT) { + dev_err(&udev->dev, "non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } /* * xHCI uses normal TRBs for both bulk and interrupt. When the @@ -1097,7 +1109,7 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, * (at most) one TD. A TD (comprised of sg list entries) can * take several service intervals to transmit. */ - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, 0); } /** @@ -1112,10 +1124,12 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, int timeout_ms) { - if (usb_pipetype(pipe) != PIPE_BULK) + if (usb_pipetype(pipe) != PIPE_BULK) { + dev_err(&udev->dev, "non-bulk pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, timeout_ms); } /** @@ -1131,13 +1145,16 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, */ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, - struct devrequest *setup, int root_portnr) + struct devrequest *setup, int root_portnr, + unsigned int timeout_ms) { struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); int ret = 0; - if (usb_pipetype(pipe) != PIPE_CONTROL) + if (usb_pipetype(pipe) != PIPE_CONTROL) { + dev_err(&udev->dev, "non-control pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } if (usb_pipedevice(pipe) == ctrl->rootdev) return xhci_submit_root(udev, pipe, buffer, setup); @@ -1155,7 +1172,7 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, } } - return xhci_ctrl_tx(udev, pipe, setup, length, buffer); + return xhci_ctrl_tx(udev, pipe, setup, length, buffer, timeout_ms); } static int xhci_lowlevel_init(struct xhci_ctrl *ctrl) @@ -1180,21 +1197,23 @@ static int xhci_lowlevel_init(struct xhci_ctrl *ctrl) /* initializing xhci data structures */ if (xhci_mem_init(ctrl, hccr, hcor) < 0) return -ENOMEM; + ctrl->hub_desc = descriptor.hub; reg = xhci_readl(&hccr->cr_hcsparams1); - descriptor.hub.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> - HCS_MAX_PORTS_SHIFT); + ctrl->hub_desc.bNbrPorts = HCS_MAX_PORTS(reg); + + dev_dbg(ctrl->dev, "Register 0x%x NbrPorts %d\n", reg, ctrl->hub_desc.bNbrPorts); /* Port Indicators */ reg = xhci_readl(&hccr->cr_hccparams); if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x80, &ctrl->hub_desc.wHubCharacteristics); /* Port Power Control */ if (HCC_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x01, &ctrl->hub_desc.wHubCharacteristics); if (xhci_start(ctrl)) { xhci_reset(ctrl); @@ -1217,6 +1236,8 @@ static int xhci_lowlevel_stop(struct xhci_ctrl *ctrl) xhci_reset(ctrl); + dev_dbg(ctrl->dev, "Disabling event ring interrupts\n"); + temp = xhci_readl(&ctrl->hcor->or_usbsts); xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT); temp = xhci_readl(&ctrl->ir_set->irq_pending); @@ -1239,7 +1260,7 @@ static int xhci_submit_control_msg(struct usb_device *udev, } return _xhci_submit_control_msg(udev, pipe, buffer, length, setup, - root_portnr); + root_portnr, timeout_ms); } static int xhci_submit_bulk_msg(struct usb_device *udev, @@ -1343,7 +1364,7 @@ static __maybe_unused int xhci_get_max_xfer_size(size_t *size) int xhci_register(struct xhci_ctrl *ctrl) { struct usb_host *host; - struct device_d *dev = ctrl->dev; + struct device *dev = ctrl->dev; int ret; dev_dbg(dev, "%s: hccr=%p, hcor=%p\n", __func__, ctrl->hccr, ctrl->hcor); @@ -1358,7 +1379,11 @@ int xhci_register(struct xhci_ctrl *ctrl) */ host->no_desc_before_addr = true; - host->hw_dev = dev; + /* + * If xHCI doesn't have its own DT node, it'll be a child of a + * physical USB host controller device that should be used for DMA + */ + host->hw_dev = dev_of_node(dev) ? dev : dev->parent; host->submit_int_msg = xhci_submit_int_msg; host->submit_control_msg = xhci_submit_control_msg; host->submit_bulk_msg = xhci_submit_bulk_msg; @@ -1393,7 +1418,7 @@ int xhci_deregister(struct xhci_ctrl *ctrl) * xHCI platform driver */ -static int xhci_probe(struct device_d *dev) +static int xhci_probe(struct device *dev) { struct resource *iores; struct xhci_ctrl *ctrl; @@ -1414,14 +1439,14 @@ static int xhci_probe(struct device_d *dev) return xhci_register(ctrl); } -static void xhci_remove(struct device_d *dev) +static void xhci_remove(struct device *dev) { struct xhci_ctrl *ctrl = dev->priv; xhci_deregister(ctrl); } -static struct driver_d xhci_driver = { +static struct driver xhci_driver = { .name = "xHCI", .probe = xhci_probe, .remove = xhci_remove, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9ffbb103d5..37e8cee843 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * USB HOST XHCI Controller * @@ -16,7 +16,7 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_ -#include <asm/types.h> +#include <linux/types.h> #include <io.h> #include <io-64-nonatomic-lo-hi.h> #include <linux/list.h> @@ -30,8 +30,8 @@ /* Section 5.3.3 - MaxPorts */ #define MAX_HC_PORTS 255 -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) +/* Up to 32 ms to halt an HC */ +#define XHCI_MAX_HALT_USEC (32*1000) #define XHCI_MAX_RESET_USEC (250*1000) @@ -490,6 +490,7 @@ struct xhci_container_ctx { int size; u8 *bytes; + dma_addr_t dma; }; /** @@ -691,6 +692,8 @@ struct xhci_input_control_ctx { struct xhci_device_context_array { /* 64-bit device addresses; we only write 32-bit addresses */ __le64 dev_context_ptrs[MAX_HC_SLOTS]; + /* private xHCD pointers */ + dma_addr_t dma; }; /* TODO: write function to set the 64-bit device DMA address */ /* @@ -903,6 +906,8 @@ union xhci_trb { /* TRB type IDs */ typedef enum { + /* reserved, used as a software sentinel */ + TRB_NONE = 0, /* bulk, interrupt, isoc scatter/gather, and control data stage */ TRB_NORMAL = 1, /* setup stage for control transfers */ @@ -1003,6 +1008,7 @@ struct xhci_segment { union xhci_trb *trbs; /* private to HCD */ struct xhci_segment *next; + dma_addr_t dma; }; struct xhci_ring { @@ -1031,11 +1037,14 @@ struct xhci_erst_entry { struct xhci_erst { struct xhci_erst_entry *entries; unsigned int num_entries; + /* xhci->event_ring keeps track of segment dma addresses */ + dma_addr_t erst_dma_addr; /* Num entries the ERST can contain */ unsigned int erst_size; }; struct xhci_scratchpad { + void *scratchpad; u64 *sp_array; }; @@ -1134,8 +1143,6 @@ void xhci_hcd_stop(int index); /************************************************************* EXTENDED CAPABILITY DEFINITIONS *************************************************************/ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) /* HC not running - set to 1 when run/stop bit is cleared. */ #define XHCI_STS_HALT (1 << 0) @@ -1203,7 +1210,7 @@ void xhci_hcd_stop(int index); struct xhci_ctrl { struct usb_host host; - struct device_d *dev; + struct device *dev; struct xhci_hccr *hccr; /* R/O registers, not need for volatile */ struct xhci_hcor *hcor; struct xhci_doorbell_array *dba; @@ -1218,6 +1225,7 @@ struct xhci_ctrl { struct xhci_erst_entry entry[ERST_NUM_SEGS]; struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; + struct usb_hub_descriptor hub_desc; void *bounce_buffer; int rootdev; }; @@ -1227,7 +1235,7 @@ static inline struct xhci_ctrl *to_xhci(struct usb_host *host) return container_of(host, struct xhci_ctrl, host); } -unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); +dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, @@ -1244,14 +1252,16 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *out_ctx); void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, struct usb_device *udev, int hop_portnr); -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, +void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd); void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); +#define XHCI_TIMEOUT_DEFAULT 5000 +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + unsigned int timeout_ms); int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); + int length, void *buffer, unsigned int timeout_ms); int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, void *buffer); + struct devrequest *req, int length, void *buffer, unsigned int timeout_ms); int xhci_check_maxpacket(struct usb_device *udev); void xhci_flush_cache(uintptr_t addr, u32 type_len); void xhci_inval_cache(uintptr_t addr, u32 type_len); |