History

USB: use genalloc for USB HCs with local memory

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.

Laurentiu Tudor committed 7 years ago

Commit b0310c21 parent da83a727 files · +102 −9Browse files

Unified · Split

7 files
  1. drivers/usb/Kconfig +1 −0
  2. drivers/usb/core/buffer.c +9 −0
  3. drivers/usb/core/hcd.c +36 −0
  4. drivers/usb/host/ohci-hcd.c +18 −5
  5. drivers/usb/host/ohci-mem.c +31 −4
  6. drivers/usb/host/ohci.h +2 −0
  7. include/linux/usb/hcd.h +5 −0
drivers/usb/Kconfig+1−0
@@ -45,6 +45,7 @@ config USB_ARCH_HAS_HCD · 44 unmodified lines
4545 config USB
4646 tristate "Support for Host-side USB"
4747 depends on USB_ARCH_HAS_HCD
48+ select GENERIC_ALLOCATOR
4849 select USB_COMMON
4950 select NLS # for UTF-8 strings
5051 ---help---
drivers/usb/core/buffer.c+9−0
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <linux/io.h>
1717 #include <linux/dma-mapping.h>
1818 #include <linux/dmapool.h>
19+#include <linux/genalloc.h>
1920 #include <linux/usb.h>
2021 #include <linux/usb/hcd.h>
2122
@@ -124,6 +125,9 @@ void *hcd_buffer_alloc( · 102 unmodified lines
124125 if (size == 0)
125126 return NULL;
126127
128+ if (hcd->localmem_pool)
129+ return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
130+
127131 /* some USB hosts just use PIO */
128132 if (!IS_ENABLED(CONFIG_HAS_DMA) ||
129133 (!is_device_dma_capable(bus->sysdev) &&
@@ -152,6 +156,11 @@ void hcd_buffer_free( · 22 unmodified lines
152156 if (!addr)
153157 return;
154158
159+ if (hcd->localmem_pool) {
160+ gen_pool_free(hcd->localmem_pool, (unsigned long)addr, size);
161+ return;
162+ }
163+
155164 if (!IS_ENABLED(CONFIG_HAS_DMA) ||
156165 (!is_device_dma_capable(bus->sysdev) &&
157166 !(hcd->driver->flags & HCD_LOCAL_MEM))) {
drivers/usb/core/hcd.c+36−0
@@ -29,6 +29,8 @@ · 28 unmodified lines
2929 #include <linux/workqueue.h>
3030 #include <linux/pm_runtime.h>
3131 #include <linux/types.h>
32+#include <linux/genalloc.h>
33+#include <linux/io.h>
3234
3335 #include <linux/phy/phy.h>
3436 #include <linux/usb.h>
@@ -3039,6 +3041,40 @@ usb_hcd_platform_shutdown(struct platform_device *dev) · 3004 unmodified lines
30393041 }
30403042 EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
30413043
3044+int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
3045+ dma_addr_t dma, size_t size)
3046+{
3047+ int err;
3048+ void *local_mem;
3049+
3050+ hcd->localmem_pool = devm_gen_pool_create(hcd->self.sysdev, PAGE_SHIFT,
3051+ dev_to_node(hcd->self.sysdev),
3052+ dev_name(hcd->self.sysdev));
3053+ if (IS_ERR(hcd->localmem_pool))
3054+ return PTR_ERR(hcd->localmem_pool);
3055+
3056+ local_mem = devm_memremap(hcd->self.sysdev, phys_addr,
3057+ size, MEMREMAP_WC);
3058+ if (!local_mem)
3059+ return -ENOMEM;
3060+
3061+ /*
3062+ * Here we pass a dma_addr_t but the arg type is a phys_addr_t.
3063+ * It's not backed by system memory and thus there's no kernel mapping
3064+ * for it.
3065+ */
3066+ err = gen_pool_add_virt(hcd->localmem_pool, (unsigned long)local_mem,
3067+ dma, size, dev_to_node(hcd->self.sysdev));
3068+ if (err < 0) {
3069+ dev_err(hcd->self.sysdev, "gen_pool_add_virt failed with %d\n",
3070+ err);
3071+ return err;
3072+ }
3073+
3074+ return 0;
3075+}
3076+EXPORT_SYMBOL_GPL(usb_hcd_setup_local_mem);
3077+
30423078 /*-------------------------------------------------------------------------*/
30433079
30443080 #if IS_ENABLED(CONFIG_USB_MON)
drivers/usb/host/ohci-hcd.c+18−5
@@ -40,6 +40,7 @@ · 39 unmodified lines
4040 #include <linux/dmapool.h>
4141 #include <linux/workqueue.h>
4242 #include <linux/debugfs.h>
43+#include <linux/genalloc.h>
4344
4445 #include <asm/io.h>
4546 #include <asm/irq.h>
@@ -505,8 +506,15 @@ static int ohci_init (struct ohci_hcd *ohci) · 459 unmodified lines
505506 timer_setup(&ohci->io_watchdog, io_watchdog_func, 0);
506507 ohci->prev_frame_no = IO_WATCHDOG_OFF;
507508
508− ohci->hcca = dma_alloc_coherent (hcd->self.controller,
509− sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
509+ if (hcd->localmem_pool)
510+ ohci->hcca = gen_pool_dma_alloc(hcd->localmem_pool,
511+ sizeof(*ohci->hcca),
512+ &ohci->hcca_dma);
513+ else
514+ ohci->hcca = dma_alloc_coherent(hcd->self.controller,
515+ sizeof(*ohci->hcca),
516+ &ohci->hcca_dma,
517+ GFP_KERNEL);
510518 if (!ohci->hcca)
511519 return -ENOMEM;
512520
@@ -990,9 +998,14 @@ static void ohci_stop (struct usb_hcd *hcd) · 477 unmodified lines
990998 remove_debug_files (ohci);
991999 ohci_mem_cleanup (ohci);
9921000 if (ohci->hcca) {
993− dma_free_coherent (hcd->self.controller,
994− sizeof *ohci->hcca,
995− ohci->hcca, ohci->hcca_dma);
1001+ if (hcd->localmem_pool)
1002+ gen_pool_free(hcd->localmem_pool,
1003+ (unsigned long)ohci->hcca,
1004+ sizeof(*ohci->hcca));
1005+ else
1006+ dma_free_coherent(hcd->self.controller,
1007+ sizeof(*ohci->hcca),
1008+ ohci->hcca, ohci->hcca_dma);
9961009 ohci->hcca = NULL;
9971010 ohci->hcca_dma = 0;
9981011 }
drivers/usb/host/ohci-mem.c+31−4
@@ -36,6 +36,13 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) · 35 unmodified lines
3636
3737 static int ohci_mem_init (struct ohci_hcd *ohci)
3838 {
39+ /*
40+ * HCs with local memory allocate from localmem_pool so there's
41+ * no need to create the below dma pools.
42+ */
43+ if (ohci_to_hcd(ohci)->localmem_pool)
44+ return 0;
45+
3946 ohci->td_cache = dma_pool_create ("ohci_td",
4047 ohci_to_hcd(ohci)->self.controller,
4148 sizeof (struct td),
@@ -84,8 +91,12 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 42 unmodified lines
8491 {
8592 dma_addr_t dma;
8693 struct td *td;
94+ struct usb_hcd *hcd = ohci_to_hcd(hc);
8795
88− td = dma_pool_zalloc (hc->td_cache, mem_flags, &dma);
96+ if (hcd->localmem_pool)
97+ td = gen_pool_dma_zalloc(hcd->localmem_pool, sizeof(*td), &dma);
98+ else
99+ td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma);
89100 if (td) {
90101 /* in case hc fetches it, make it look dead */
91102 td->hwNextTD = cpu_to_hc32 (hc, dma);
@@ -99,6 +110,7 @@ static void · 7 unmodified lines
99110 td_free (struct ohci_hcd *hc, struct td *td)
100111 {
101112 struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
113+ struct usb_hcd *hcd = ohci_to_hcd(hc);
102114
103115 while (*prev && *prev != td)
104116 prev = &(*prev)->td_hash;
@@ -106,7 +118,12 @@ td_free (struct ohci_hcd *hc, struct td *td) · 1 unmodified line
106118 *prev = td->td_hash;
107119 else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
108120 ohci_dbg (hc, "no hash for td %p\n", td);
109− dma_pool_free (hc->td_cache, td, td->td_dma);
121+
122+ if (hcd->localmem_pool)
123+ gen_pool_free(hcd->localmem_pool, (unsigned long)td,
124+ sizeof(*td));
125+ else
126+ dma_pool_free(hc->td_cache, td, td->td_dma);
110127 }
111128
112129 /*-------------------------------------------------------------------------*/
@@ -117,8 +134,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 4 unmodified lines
117134 {
118135 dma_addr_t dma;
119136 struct ed *ed;
137+ struct usb_hcd *hcd = ohci_to_hcd(hc);
120138
121− ed = dma_pool_zalloc (hc->ed_cache, mem_flags, &dma);
139+ if (hcd->localmem_pool)
140+ ed = gen_pool_dma_zalloc(hcd->localmem_pool, sizeof(*ed), &dma);
141+ else
142+ ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma);
122143 if (ed) {
123144 INIT_LIST_HEAD (&ed->td_list);
124145 ed->dma = dma;
@@ -129,6 +150,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 4 unmodified lines
129150 static void
130151 ed_free (struct ohci_hcd *hc, struct ed *ed)
131152 {
132− dma_pool_free (hc->ed_cache, ed, ed->dma);
153+ struct usb_hcd *hcd = ohci_to_hcd(hc);
154+
155+ if (hcd->localmem_pool)
156+ gen_pool_free(hcd->localmem_pool, (unsigned long)ed,
157+ sizeof(*ed));
158+ else
159+ dma_pool_free(hc->ed_cache, ed, ed->dma);
133160 }
134161
drivers/usb/host/ohci.h+2−0
@@ -385,6 +385,8 @@ struct ohci_hcd { · 384 unmodified lines
385385
386386 /*
387387 * memory management for queue data structures
388+ *
389+ * @td_cache and @ed_cache are %NULL if &usb_hcd.localmem_pool is used.
388390 */
389391 struct dma_pool *td_cache;
390392 struct dma_pool *ed_cache;
include/linux/usb/hcd.h+5−0
@@ -216,6 +216,9 @@ struct usb_hcd { · 215 unmodified lines
216216 #define HC_IS_RUNNING(state) ((state) & __ACTIVE)
217217 #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
218218
219+ /* memory pool for HCs having local memory, or %NULL */
220+ struct gen_pool *localmem_pool;
221+
219222 /* more shared queuing code would be good; it should support
220223 * smarter scheduling, handle transaction translators, etc;
221224 * input size of periodic table to an interrupt scheduler.
@@ -461,6 +464,8 @@ extern int usb_add_hcd(struct usb_hcd *hcd, · 239 unmodified lines
461464 unsigned int irqnum, unsigned long irqflags);
462465 extern void usb_remove_hcd(struct usb_hcd *hcd);
463466 extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
467+int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
468+ dma_addr_t dma, size_t size);
464469
465470 struct platform_device;
466471 extern void usb_hcd_platform_shutdown(struct platform_device *dev);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t