Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
This patch series backports the following upstream patches:
01: da83a722959a82733c3ca60030cc364ca2318c5a lib/genalloc: add gen_pool_dma_zalloc() for zeroed DMA allocations
02: b0310c2f09bbe8aebefb97ed67949a3a7092aca6 USB: use genalloc for USB HCs with local memory
03: 2d7a3dc3e24f43504b1f25eae8195e600f4cce8b USB: drop HCD_LOCAL_MEM flag
04: dd3ecf17ba70a70d2c9ef9ba725281b84f8eef12 usb: don't create dma pools for HCDs with a localmem_pool
05: edfbcb321faf07ca970e4191abe061deeb7d3788 usb: add a hcd_uses_dma helper
Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com
commit da83a722959a82733c3ca60030cc364ca2318c5a upstream.
gen_pool_dma_zalloc() is a zeroed memory variant of gen_pool_dma_alloc(). Also document the return values of both, and indicate NULL as a "%NULL" constant.
Signed-off-by: Fredrik Noring noring@nocrew.org Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com --- include/linux/genalloc.h | 1 + lib/genalloc.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index dd0a452373e7..6c62eeca754f 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -121,6 +121,7 @@ extern unsigned long gen_pool_alloc_algo(struct gen_pool *, size_t, genpool_algo_t algo, void *data); extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); +void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); extern void gen_pool_for_each_chunk(struct gen_pool *, void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); diff --git a/lib/genalloc.c b/lib/genalloc.c index 7e85d1e37a6e..5db43476a19b 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -337,12 +337,14 @@ EXPORT_SYMBOL(gen_pool_alloc_algo); * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage * @pool: pool to allocate from * @size: number of bytes to allocate from the pool - * @dma: dma-view physical address return value. Use NULL if unneeded. + * @dma: dma-view physical address return value. Use %NULL if unneeded. * * Allocate the requested number of bytes from the specified pool. * Uses the pool allocation function (with first-fit algorithm by default). * Can not be used in NMI handler on architectures without * NMI-safe cmpxchg implementation. + * + * Return: virtual address of the allocated memory, or %NULL on failure */ void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma) { @@ -362,6 +364,31 @@ void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma) } EXPORT_SYMBOL(gen_pool_dma_alloc);
+/** + * gen_pool_dma_zalloc - allocate special zeroed memory from the pool for + * DMA usage + * @pool: pool to allocate from + * @size: number of bytes to allocate from the pool + * @dma: dma-view physical address return value. Use %NULL if unneeded. + * + * Allocate the requested number of zeroed bytes from the specified pool. + * Uses the pool allocation function (with first-fit algorithm by default). + * Can not be used in NMI handler on architectures without + * NMI-safe cmpxchg implementation. + * + * Return: virtual address of the allocated zeroed memory, or %NULL on failure + */ +void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma) +{ + void *vaddr = gen_pool_dma_alloc(pool, size, dma); + + if (vaddr) + memset(vaddr, 0, size); + + return vaddr; +} +EXPORT_SYMBOL(gen_pool_dma_zalloc); + /** * gen_pool_free - free allocated special memory back to the pool * @pool: pool to free to
commit b0310c2f09bbe8aebefb97ed67949a3a7092aca6 upstream.
For HCs that have local memory, replace the current DMA API usage with a genalloc generic allocator to manage the mappings for these devices. To help users, introduce a new HCD API, usb_hcd_setup_local_mem() that will setup up the genalloc backing up the device local memory. It will be used in subsequent patches. This is in preparation for dropping the existing "coherent" dma mem declaration APIs. The current implementation was relying on a short circuit in the DMA API that in the end, was acting as an allocator for these type of devices.
Signed-off-by: Laurentiu Tudor laurentiu.tudor@nxp.com Tested-by: Fredrik Noring noring@nocrew.org Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com --- drivers/usb/Kconfig | 1 + drivers/usb/core/buffer.c | 9 +++++++++ drivers/usb/core/hcd.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci-hcd.c | 23 ++++++++++++++++++----- drivers/usb/host/ohci-mem.c | 35 +++++++++++++++++++++++++++++++---- drivers/usb/host/ohci.h | 2 ++ include/linux/usb/hcd.h | 5 +++++ 7 files changed, 102 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 70e6c956c23c..2b3a76eaa653 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -44,6 +44,7 @@ config USB_ARCH_HAS_HCD config USB tristate "Support for Host-side USB" depends on USB_ARCH_HAS_HCD + select GENERIC_ALLOCATOR select USB_COMMON select NLS # for UTF-8 strings ---help--- diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 77eef8acff94..a9392b63c175 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -16,6 +16,7 @@ #include <linux/io.h> #include <linux/dma-mapping.h> #include <linux/dmapool.h> +#include <linux/genalloc.h> #include <linux/usb.h> #include <linux/usb/hcd.h>
@@ -128,6 +129,9 @@ void *hcd_buffer_alloc( if (size == 0) return NULL;
+ if (hcd->localmem_pool) + return gen_pool_dma_alloc(hcd->localmem_pool, size, dma); + /* some USB hosts just use PIO */ if (!IS_ENABLED(CONFIG_HAS_DMA) || (!is_device_dma_capable(bus->sysdev) && @@ -156,6 +160,11 @@ void hcd_buffer_free( if (!addr) return;
+ if (hcd->localmem_pool) { + gen_pool_free(hcd->localmem_pool, (unsigned long)addr, size); + return; + } + if (!IS_ENABLED(CONFIG_HAS_DMA) || (!is_device_dma_capable(bus->sysdev) && !(hcd->driver->flags & HCD_LOCAL_MEM))) { diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index b82a7d787add..c1daf3f646d6 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -29,6 +29,8 @@ #include <linux/workqueue.h> #include <linux/pm_runtime.h> #include <linux/types.h> +#include <linux/genalloc.h> +#include <linux/io.h>
#include <linux/phy/phy.h> #include <linux/usb.h> @@ -3025,6 +3027,40 @@ usb_hcd_platform_shutdown(struct platform_device *dev) } EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
+int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr, + dma_addr_t dma, size_t size) +{ + int err; + void *local_mem; + + hcd->localmem_pool = devm_gen_pool_create(hcd->self.sysdev, PAGE_SHIFT, + dev_to_node(hcd->self.sysdev), + dev_name(hcd->self.sysdev)); + if (IS_ERR(hcd->localmem_pool)) + return PTR_ERR(hcd->localmem_pool); + + local_mem = devm_memremap(hcd->self.sysdev, phys_addr, + size, MEMREMAP_WC); + if (!local_mem) + return -ENOMEM; + + /* + * Here we pass a dma_addr_t but the arg type is a phys_addr_t. + * It's not backed by system memory and thus there's no kernel mapping + * for it. + */ + err = gen_pool_add_virt(hcd->localmem_pool, (unsigned long)local_mem, + dma, size, dev_to_node(hcd->self.sysdev)); + if (err < 0) { + dev_err(hcd->self.sysdev, "gen_pool_add_virt failed with %d\n", + err); + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(usb_hcd_setup_local_mem); + /*-------------------------------------------------------------------------*/
#if IS_ENABLED(CONFIG_USB_MON) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index af11887f5f9e..9b2d8b84ae26 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -40,6 +40,7 @@ #include <linux/dmapool.h> #include <linux/workqueue.h> #include <linux/debugfs.h> +#include <linux/genalloc.h>
#include <asm/io.h> #include <asm/irq.h> @@ -514,8 +515,15 @@ static int ohci_init (struct ohci_hcd *ohci) timer_setup(&ohci->io_watchdog, io_watchdog_func, 0); ohci->prev_frame_no = IO_WATCHDOG_OFF;
- ohci->hcca = dma_alloc_coherent (hcd->self.controller, - sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL); + if (hcd->localmem_pool) + ohci->hcca = gen_pool_dma_alloc(hcd->localmem_pool, + sizeof(*ohci->hcca), + &ohci->hcca_dma); + else + ohci->hcca = dma_alloc_coherent(hcd->self.controller, + sizeof(*ohci->hcca), + &ohci->hcca_dma, + GFP_KERNEL); if (!ohci->hcca) return -ENOMEM;
@@ -999,9 +1007,14 @@ static void ohci_stop (struct usb_hcd *hcd) remove_debug_files (ohci); ohci_mem_cleanup (ohci); if (ohci->hcca) { - dma_free_coherent (hcd->self.controller, - sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); + if (hcd->localmem_pool) + gen_pool_free(hcd->localmem_pool, + (unsigned long)ohci->hcca, + sizeof(*ohci->hcca)); + else + dma_free_coherent(hcd->self.controller, + sizeof(*ohci->hcca), + ohci->hcca, ohci->hcca_dma); ohci->hcca = NULL; ohci->hcca_dma = 0; } diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index b3da3f12e5b1..8e15044be14c 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -36,6 +36,13 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
static int ohci_mem_init (struct ohci_hcd *ohci) { + /* + * HCs with local memory allocate from localmem_pool so there's + * no need to create the below dma pools. + */ + if (ohci_to_hcd(ohci)->localmem_pool) + return 0; + ohci->td_cache = dma_pool_create ("ohci_td", ohci_to_hcd(ohci)->self.controller, sizeof (struct td), @@ -88,8 +95,12 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) { dma_addr_t dma; struct td *td; + struct usb_hcd *hcd = ohci_to_hcd(hc);
- td = dma_pool_zalloc (hc->td_cache, mem_flags, &dma); + if (hcd->localmem_pool) + td = gen_pool_dma_zalloc(hcd->localmem_pool, sizeof(*td), &dma); + else + td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma); if (td) { /* in case hc fetches it, make it look dead */ td->hwNextTD = cpu_to_hc32 (hc, dma); @@ -103,6 +114,7 @@ static void td_free (struct ohci_hcd *hc, struct td *td) { struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)]; + struct usb_hcd *hcd = ohci_to_hcd(hc);
while (*prev && *prev != td) prev = &(*prev)->td_hash; @@ -110,7 +122,12 @@ td_free (struct ohci_hcd *hc, struct td *td) *prev = td->td_hash; else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0) ohci_dbg (hc, "no hash for td %p\n", td); - dma_pool_free (hc->td_cache, td, td->td_dma); + + if (hcd->localmem_pool) + gen_pool_free(hcd->localmem_pool, (unsigned long)td, + sizeof(*td)); + else + dma_pool_free(hc->td_cache, td, td->td_dma); }
/*-------------------------------------------------------------------------*/ @@ -121,8 +138,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) { dma_addr_t dma; struct ed *ed; + struct usb_hcd *hcd = ohci_to_hcd(hc);
- ed = dma_pool_zalloc (hc->ed_cache, mem_flags, &dma); + if (hcd->localmem_pool) + ed = gen_pool_dma_zalloc(hcd->localmem_pool, sizeof(*ed), &dma); + else + ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma); if (ed) { INIT_LIST_HEAD (&ed->td_list); ed->dma = dma; @@ -133,6 +154,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) static void ed_free (struct ohci_hcd *hc, struct ed *ed) { - dma_pool_free (hc->ed_cache, ed, ed->dma); + struct usb_hcd *hcd = ohci_to_hcd(hc); + + if (hcd->localmem_pool) + gen_pool_free(hcd->localmem_pool, (unsigned long)ed, + sizeof(*ed)); + else + dma_pool_free(hc->ed_cache, ed, ed->dma); }
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index ef4813bfc5bf..b015b00774b2 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -385,6 +385,8 @@ struct ohci_hcd {
/* * memory management for queue data structures + * + * @td_cache and @ed_cache are %NULL if &usb_hcd.localmem_pool is used. */ struct dma_pool *td_cache; struct dma_pool *ed_cache; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 97e2ddec18b1..5f1d57064cc0 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -211,6 +211,9 @@ struct usb_hcd { #define HC_IS_RUNNING(state) ((state) & __ACTIVE) #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
+ /* memory pool for HCs having local memory, or %NULL */ + struct gen_pool *localmem_pool; + /* more shared queuing code would be good; it should support * smarter scheduling, handle transaction translators, etc; * input size of periodic table to an interrupt scheduler. @@ -461,6 +464,8 @@ extern int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags); extern void usb_remove_hcd(struct usb_hcd *hcd); extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1); +int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr, + dma_addr_t dma, size_t size);
struct platform_device; extern void usb_hcd_platform_shutdown(struct platform_device *dev);
commit 2d7a3dc3e24f43504b1f25eae8195e600f4cce8b upstream.
With the addition of the local memory allocator, the HCD_LOCAL_MEM flag can be dropped and the checks against it replaced with a check for the localmem_pool ptr being initialized.
Signed-off-by: Laurentiu Tudor laurentiu.tudor@nxp.com Tested-by: Fredrik Noring noring@nocrew.org Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com --- drivers/usb/core/buffer.c | 8 +++----- drivers/usb/core/hcd.c | 15 ++++++--------- drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/fotg210-hcd.c | 2 +- drivers/usb/host/ohci-hcd.c | 2 +- drivers/usb/host/ohci-sm501.c | 2 +- drivers/usb/host/ohci-tmio.c | 2 +- drivers/usb/host/uhci-hcd.c | 2 +- include/linux/usb/hcd.h | 1 - 9 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index a9392b63c175..d93e25aeaf96 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -68,7 +68,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
if (!IS_ENABLED(CONFIG_HAS_DMA) || (!is_device_dma_capable(hcd->self.sysdev) && - !(hcd->driver->flags & HCD_LOCAL_MEM))) + !hcd->localmem_pool)) return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) { @@ -134,8 +134,7 @@ void *hcd_buffer_alloc(
/* some USB hosts just use PIO */ if (!IS_ENABLED(CONFIG_HAS_DMA) || - (!is_device_dma_capable(bus->sysdev) && - !(hcd->driver->flags & HCD_LOCAL_MEM))) { + !is_device_dma_capable(bus->sysdev)) { *dma = ~(dma_addr_t) 0; return kmalloc(size, mem_flags); } @@ -166,8 +165,7 @@ void hcd_buffer_free( }
if (!IS_ENABLED(CONFIG_HAS_DMA) || - (!is_device_dma_capable(bus->sysdev) && - !(hcd->driver->flags & HCD_LOCAL_MEM))) { + !is_device_dma_capable(bus->sysdev)) { kfree(addr); return; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index c1daf3f646d6..c991e7ff1875 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1346,14 +1346,14 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); * using regular system memory - like pci devices doing bus mastering. * * To support host controllers with limited dma capabilities we provide dma - * bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag. + * bounce buffers. This feature can be enabled by initializing + * hcd->localmem_pool using usb_hcd_setup_local_mem(). * For this to work properly the host controller code must first use the * function dma_declare_coherent_memory() to point out which memory area * that should be used for dma allocations. * - * The HCD_LOCAL_MEM flag then tells the usb code to allocate all data for - * dma using dma_alloc_coherent() which in turn allocates from the memory - * area pointed out with dma_declare_coherent_memory(). + * The initialized hcd->localmem_pool then tells the usb code to allocate all + * data for dma using the genalloc API. * * So, to summarize... * @@ -1363,9 +1363,6 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); * (a) "normal" kernel memory is no good, and * (b) there's not enough to share * - * - The only *portable* hook for such stuff in the - * DMA framework is dma_declare_coherent_memory() - * * - So we use that, even though the primary requirement * is that the memory be "local" (hence addressable * by that device), not "coherent". @@ -1532,7 +1529,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, urb->setup_dma)) return -EAGAIN; urb->transfer_flags |= URB_SETUP_MAP_SINGLE; - } else if (hcd->driver->flags & HCD_LOCAL_MEM) { + } else if (hcd->localmem_pool) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, &urb->setup_dma, @@ -1602,7 +1599,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, else urb->transfer_flags |= URB_DMA_MAP_SINGLE; } - } else if (hcd->driver->flags & HCD_LOCAL_MEM) { + } else if (hcd->localmem_pool) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, &urb->transfer_dma, diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8608ac513fb7..f0a0ddee52d0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -559,7 +559,7 @@ static int ehci_init(struct usb_hcd *hcd) ehci->command = temp;
/* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + if (!hcd->localmem_pool) hcd->self.sg_tablesize = ~0;
/* Prepare for unlinking active QHs */ diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 2d5a72c15069..cfaf03008a13 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -4998,7 +4998,7 @@ static int hcd_fotg210_init(struct usb_hcd *hcd) fotg210->command = temp;
/* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + if (!hcd->localmem_pool) hcd->self.sg_tablesize = ~0; return 0; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9b2d8b84ae26..81a104fafbc2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -457,7 +457,7 @@ static int ohci_init (struct ohci_hcd *ohci) struct usb_hcd *hcd = ohci_to_hcd(ohci);
/* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + if (!hcd->localmem_pool) hcd->self.sg_tablesize = ~0;
if (distrust_firmware) diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 0a39dc58f376..f9b1279b68ec 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -49,7 +49,7 @@ static const struct hc_driver ohci_sm501_hc_driver = { * generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM, + .flags = HCD_USB11 | HCD_MEMORY,
/* * basic lifecycle operations diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index a631dbb369d7..98ecf3e3d74f 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -153,7 +153,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {
/* generic hardware linkage */ .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM, + .flags = HCD_USB11 | HCD_MEMORY,
/* basic lifecycle operations */ .start = ohci_tmio_start, diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6218bfe54f52..b4f4f729e080 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -581,7 +581,7 @@ static int uhci_start(struct usb_hcd *hcd)
hcd->uses_new_polling = 1; /* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + if (!hcd->localmem_pool) hcd->self.sg_tablesize = ~0;
spin_lock_init(&uhci->lock); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 5f1d57064cc0..e24dade77132 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -256,7 +256,6 @@ struct hc_driver {
int flags; #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ -#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ #define HCD_USB11 0x0010 /* USB 1.1 */ #define HCD_USB2 0x0020 /* USB 2.0 */
commit dd3ecf17ba70a70d2c9ef9ba725281b84f8eef12 upstream.
If the HCD provides a localmem pool we will never use the DMA pools, so don't create them.
Fixes: b0310c2f09bb ("USB: use genalloc for USB HCs with local memory") Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20190811080520.21712-2-hch@lst.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com --- drivers/usb/core/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index d93e25aeaf96..8f1697bcc170 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -66,9 +66,9 @@ int hcd_buffer_create(struct usb_hcd *hcd) char name[16]; int i, size;
- if (!IS_ENABLED(CONFIG_HAS_DMA) || - (!is_device_dma_capable(hcd->self.sysdev) && - !hcd->localmem_pool)) + if (hcd->localmem_pool || + !IS_ENABLED(CONFIG_HAS_DMA) || + !is_device_dma_capable(hcd->self.sysdev)) return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
commit edfbcb321faf07ca970e4191abe061deeb7d3788 upstream.
The USB buffer allocation code is the only place in the usb core (and in fact the whole kernel) that uses is_device_dma_capable, while the URB mapping code uses the uses_dma flag in struct usb_bus. Switch the buffer allocation to use the uses_dma flag used by the rest of the USB code, and create a helper in hcd.h that checks this flag as well as the CONFIG_HAS_DMA to simplify the caller a bit.
Signed-off-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20190811080520.21712-3-hch@lst.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: John L. Villalovos jlvillal@os.amperecomputing.com --- drivers/usb/core/buffer.c | 10 +++------- drivers/usb/core/hcd.c | 4 ++-- drivers/usb/dwc2/hcd.c | 2 +- include/linux/usb.h | 2 +- include/linux/usb/hcd.h | 3 +++ 5 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 8f1697bcc170..84055ed842ff 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -66,9 +66,7 @@ int hcd_buffer_create(struct usb_hcd *hcd) char name[16]; int i, size;
- if (hcd->localmem_pool || - !IS_ENABLED(CONFIG_HAS_DMA) || - !is_device_dma_capable(hcd->self.sysdev)) + if (hcd->localmem_pool || !hcd_uses_dma(hcd)) return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) { @@ -133,8 +131,7 @@ void *hcd_buffer_alloc( return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
/* some USB hosts just use PIO */ - if (!IS_ENABLED(CONFIG_HAS_DMA) || - !is_device_dma_capable(bus->sysdev)) { + if (!hcd_uses_dma(hcd)) { *dma = ~(dma_addr_t) 0; return kmalloc(size, mem_flags); } @@ -164,8 +161,7 @@ void hcd_buffer_free( return; }
- if (!IS_ENABLED(CONFIG_HAS_DMA) || - !is_device_dma_capable(bus->sysdev)) { + if (!hcd_uses_dma(hcd)) { kfree(addr); return; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index c991e7ff1875..8b8ec0c7325d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1511,7 +1511,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (usb_endpoint_xfer_control(&urb->ep->desc)) { if (hcd->self.uses_pio_for_control) return ret; - if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { + if (hcd_uses_dma(hcd)) { if (is_vmalloc_addr(urb->setup_packet)) { WARN_ONCE(1, "setup packet is not dma capable\n"); return -EAGAIN; @@ -1545,7 +1545,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; if (urb->transfer_buffer_length != 0 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { - if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { + if (hcd_uses_dma(hcd)) { if (urb->num_sgs) { int n;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index a5c8329fd462..797bb4f2a52c 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4770,7 +4770,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
buf = urb->transfer_buffer;
- if (hcd->self.uses_dma) { + if (hcd_uses_dma(hcd)) { if (!buf && (urb->transfer_dma & 3)) { dev_err(hsotg->dev, "%s: unaligned transfer with no transfer_buffer", diff --git a/include/linux/usb.h b/include/linux/usb.h index ff010d1fd1c7..667712d416c1 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1455,7 +1455,7 @@ typedef void (*usb_complete_t)(struct urb *); * field rather than determining a dma address themselves. * * Note that transfer_buffer must still be set if the controller - * does not support DMA (as indicated by bus.uses_dma) and when talking + * does not support DMA (as indicated by hcd_uses_dma()) and when talking * to root hub. If you have to trasfer between highmem zone and the device * on such controller, create a bounce buffer or bail out with an error. * If transfer_buffer cannot be set (is in highmem) and the controller is DMA diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index e24dade77132..aa69d7d5762a 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -422,6 +422,9 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd, return hcd->high_prio_bh.completing_ep == ep; }
+#define hcd_uses_dma(hcd) \ + (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma) + extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, int status);
On Tue, Sep 15, 2020 at 02:30:34PM -0700, John L. Villalovos wrote:
Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
Is this a regression, or something that has always happened? If a regression, any pointers to what commit caused this?
this really feels like a "new feature" addition to me, unless this used to work properly.
thanks,
greg k-h
On 9/15/2020 11:31 PM, Greg KH wrote:
On Tue, Sep 15, 2020 at 02:30:34PM -0700, John L. Villalovos wrote:
Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
Is this a regression, or something that has always happened? If a regression, any pointers to what commit caused this?
this really feels like a "new feature" addition to me, unless this used to work properly.
It is not a regression. It is a crash that occurs on new hardware that has this USB controller.
Without this patch series, hardware with this USB controller will fail to work. So in the choice between "regression" and "new feature" I would say "new feature".
Thanks,
John
On Wed, Sep 16, 2020 at 09:54:50AM -0700, John Villalovos wrote:
On 9/15/2020 11:31 PM, Greg KH wrote:
On Tue, Sep 15, 2020 at 02:30:34PM -0700, John L. Villalovos wrote:
Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
Is this a regression, or something that has always happened? If a regression, any pointers to what commit caused this?
this really feels like a "new feature" addition to me, unless this used to work properly.
It is not a regression. It is a crash that occurs on new hardware that has this USB controller.
Without this patch series, hardware with this USB controller will fail to work. So in the choice between "regression" and "new feature" I would say "new feature".
Ok, to support new hardware, use a newer kernel, no reason why 5.4 or newer will not work here, right?
thanks,
greg k-h
On 9/16/2020 10:08 AM, Greg KH wrote:
On Wed, Sep 16, 2020 at 09:54:50AM -0700, John Villalovos wrote:
On 9/15/2020 11:31 PM, Greg KH wrote:
On Tue, Sep 15, 2020 at 02:30:34PM -0700, John L. Villalovos wrote:
Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
Is this a regression, or something that has always happened? If a regression, any pointers to what commit caused this?
this really feels like a "new feature" addition to me, unless this used to work properly.
It is not a regression. It is a crash that occurs on new hardware that has this USB controller.
Without this patch series, hardware with this USB controller will fail to work. So in the choice between "regression" and "new feature" I would say "new feature".
Ok, to support new hardware, use a newer kernel, no reason why 5.4 or newer will not work here, right?
This is true, but some customers who want to use this hardware don't want (refuse) to use a new kernel :(
Can I take this to mean that this patch series is not allowed to go into the stable kernel?
Thanks, John
On Wed, Sep 16, 2020 at 10:15:12AM -0700, John Villalovos wrote:
On 9/16/2020 10:08 AM, Greg KH wrote:
On Wed, Sep 16, 2020 at 09:54:50AM -0700, John Villalovos wrote:
On 9/15/2020 11:31 PM, Greg KH wrote:
On Tue, Sep 15, 2020 at 02:30:34PM -0700, John L. Villalovos wrote:
Add support needed for the Renesas USB 3.0 controller (PD720201/PD720202). Without these patches a system with this USB controller will crash during boot.
Is this a regression, or something that has always happened? If a regression, any pointers to what commit caused this?
this really feels like a "new feature" addition to me, unless this used to work properly.
It is not a regression. It is a crash that occurs on new hardware that has this USB controller.
Without this patch series, hardware with this USB controller will fail to work. So in the choice between "regression" and "new feature" I would say "new feature".
Ok, to support new hardware, use a newer kernel, no reason why 5.4 or newer will not work here, right?
This is true, but some customers who want to use this hardware don't want (refuse) to use a new kernel :(
That's crazy, 4.19 should NOT be used for any system that requires new hardware. You all have read my "what kernel should I pick" guide, right?
Can I take this to mean that this patch series is not allowed to go into the stable kernel?
That is correct. Use a newer kernel, it's much better overall.
Only reason you should be stuck on 4.19 at this point in time is if you have an SoC with millions of out-of-tree lines added to it (making a Linux-like system), or you are an "enterprise" distro and you are paying for support for them.
Or you are using Debian, they know what they are doing there :)
thanks,
greg k-h
linux-stable-mirror@lists.linaro.org