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
45config USB45config USB
46 tristate "Support for Host-side USB"46 tristate "Support for Host-side USB"
47 depends on USB_ARCH_HAS_HCD47 depends on USB_ARCH_HAS_HCD
48 select GENERIC_ALLOCATOR
48 select USB_COMMON49 select USB_COMMON
49 select NLS # for UTF-8 strings50 select NLS # for UTF-8 strings
50 ---help---51 ---help---
drivers/usb/core/buffer.c+9−0
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#include <linux/io.h>16#include <linux/io.h>
17#include <linux/dma-mapping.h>17#include <linux/dma-mapping.h>
18#include <linux/dmapool.h>18#include <linux/dmapool.h>
19#include <linux/genalloc.h>
19#include <linux/usb.h>20#include <linux/usb.h>
20#include <linux/usb/hcd.h>21#include <linux/usb/hcd.h>
21 22
@@ -124,6 +125,9 @@ void *hcd_buffer_alloc( · 102 unmodified lines
124 if (size == 0)125 if (size == 0)
125 return NULL;126 return NULL;
126 127
128 if (hcd->localmem_pool)
129 return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
130
127 /* some USB hosts just use PIO */131 /* some USB hosts just use PIO */
128 if (!IS_ENABLED(CONFIG_HAS_DMA) ||132 if (!IS_ENABLED(CONFIG_HAS_DMA) ||
129 (!is_device_dma_capable(bus->sysdev) &&133 (!is_device_dma_capable(bus->sysdev) &&
@@ -152,6 +156,11 @@ void hcd_buffer_free( · 22 unmodified lines
152 if (!addr)156 if (!addr)
153 return;157 return;
154 158
159 if (hcd->localmem_pool) {
160 gen_pool_free(hcd->localmem_pool, (unsigned long)addr, size);
161 return;
162 }
163
155 if (!IS_ENABLED(CONFIG_HAS_DMA) ||164 if (!IS_ENABLED(CONFIG_HAS_DMA) ||
156 (!is_device_dma_capable(bus->sysdev) &&165 (!is_device_dma_capable(bus->sysdev) &&
157 !(hcd->driver->flags & HCD_LOCAL_MEM))) {166 !(hcd->driver->flags & HCD_LOCAL_MEM))) {
drivers/usb/core/hcd.c+36−0
@@ -29,6 +29,8 @@ · 28 unmodified lines
29#include <linux/workqueue.h>29#include <linux/workqueue.h>
30#include <linux/pm_runtime.h>30#include <linux/pm_runtime.h>
31#include <linux/types.h>31#include <linux/types.h>
32#include <linux/genalloc.h>
33#include <linux/io.h>
32 34
33#include <linux/phy/phy.h>35#include <linux/phy/phy.h>
34#include <linux/usb.h>36#include <linux/usb.h>
@@ -3039,6 +3041,40 @@ usb_hcd_platform_shutdown(struct platform_device *dev) · 3004 unmodified lines
3039}3041}
3040EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);3042EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
3041 3043
3044int 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}
3076EXPORT_SYMBOL_GPL(usb_hcd_setup_local_mem);
3077
3042/*-------------------------------------------------------------------------*/3078/*-------------------------------------------------------------------------*/
3043 3079
3044#if IS_ENABLED(CONFIG_USB_MON)3080#if IS_ENABLED(CONFIG_USB_MON)
drivers/usb/host/ohci-hcd.c+18−5
@@ -40,6 +40,7 @@ · 39 unmodified lines
40#include <linux/dmapool.h>40#include <linux/dmapool.h>
41#include <linux/workqueue.h>41#include <linux/workqueue.h>
42#include <linux/debugfs.h>42#include <linux/debugfs.h>
43#include <linux/genalloc.h>
43 44
44#include <asm/io.h>45#include <asm/io.h>
45#include <asm/irq.h>46#include <asm/irq.h>
@@ -505,8 +506,15 @@ static int ohci_init (struct ohci_hcd *ohci) · 459 unmodified lines
505 timer_setup(&ohci->io_watchdog, io_watchdog_func, 0);506 timer_setup(&ohci->io_watchdog, io_watchdog_func, 0);
506 ohci->prev_frame_no = IO_WATCHDOG_OFF;507 ohci->prev_frame_no = IO_WATCHDOG_OFF;
507 508
508 ohci->hcca = dma_alloc_coherent (hcd->self.controller,509 if (hcd->localmem_pool)
509 sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);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);
510 if (!ohci->hcca)518 if (!ohci->hcca)
511 return -ENOMEM;519 return -ENOMEM;
512 520
@@ -990,9 +998,14 @@ static void ohci_stop (struct usb_hcd *hcd) · 477 unmodified lines
990 remove_debug_files (ohci);998 remove_debug_files (ohci);
991 ohci_mem_cleanup (ohci);999 ohci_mem_cleanup (ohci);
992 if (ohci->hcca) {1000 if (ohci->hcca) {
993 dma_free_coherent (hcd->self.controller,1001 if (hcd->localmem_pool)
994 sizeof *ohci->hcca,1002 gen_pool_free(hcd->localmem_pool,
995 ohci->hcca, ohci->hcca_dma);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);
996 ohci->hcca = NULL;1009 ohci->hcca = NULL;
997 ohci->hcca_dma = 0;1010 ohci->hcca_dma = 0;
998 }1011 }
drivers/usb/host/ohci-mem.c+31−4
@@ -36,6 +36,13 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) · 35 unmodified lines
36 36
37static int ohci_mem_init (struct ohci_hcd *ohci)37static int ohci_mem_init (struct ohci_hcd *ohci)
38{38{
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
39 ohci->td_cache = dma_pool_create ("ohci_td",46 ohci->td_cache = dma_pool_create ("ohci_td",
40 ohci_to_hcd(ohci)->self.controller,47 ohci_to_hcd(ohci)->self.controller,
41 sizeof (struct td),48 sizeof (struct td),
@@ -84,8 +91,12 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 42 unmodified lines
84{91{
85 dma_addr_t dma;92 dma_addr_t dma;
86 struct td *td;93 struct td *td;
94 struct usb_hcd *hcd = ohci_to_hcd(hc);
87 95
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);
89 if (td) {100 if (td) {
90 /* in case hc fetches it, make it look dead */101 /* in case hc fetches it, make it look dead */
91 td->hwNextTD = cpu_to_hc32 (hc, dma);102 td->hwNextTD = cpu_to_hc32 (hc, dma);
@@ -99,6 +110,7 @@ static void · 7 unmodified lines
99td_free (struct ohci_hcd *hc, struct td *td)110td_free (struct ohci_hcd *hc, struct td *td)
100{111{
101 struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];112 struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
113 struct usb_hcd *hcd = ohci_to_hcd(hc);
102 114
103 while (*prev && *prev != td)115 while (*prev && *prev != td)
104 prev = &(*prev)->td_hash;116 prev = &(*prev)->td_hash;
@@ -106,7 +118,12 @@ td_free (struct ohci_hcd *hc, struct td *td) · 1 unmodified line
106 *prev = td->td_hash;118 *prev = td->td_hash;
107 else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)119 else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
108 ohci_dbg (hc, "no hash for td %p\n", td);120 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);
110}127}
111 128
112/*-------------------------------------------------------------------------*/129/*-------------------------------------------------------------------------*/
@@ -117,8 +134,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 4 unmodified lines
117{134{
118 dma_addr_t dma;135 dma_addr_t dma;
119 struct ed *ed;136 struct ed *ed;
137 struct usb_hcd *hcd = ohci_to_hcd(hc);
120 138
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);
122 if (ed) {143 if (ed) {
123 INIT_LIST_HEAD (&ed->td_list);144 INIT_LIST_HEAD (&ed->td_list);
124 ed->dma = dma;145 ed->dma = dma;
@@ -129,6 +150,12 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) · 4 unmodified lines
129static void150static void
130ed_free (struct ohci_hcd *hc, struct ed *ed)151ed_free (struct ohci_hcd *hc, struct ed *ed)
131{152{
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);
133}160}
134 161
drivers/usb/host/ohci.h+2−0
@@ -385,6 +385,8 @@ struct ohci_hcd { · 384 unmodified lines
385 385
386 /*386 /*
387 * memory management for queue data structures387 * memory management for queue data structures
388 *
389 * @td_cache and @ed_cache are %NULL if &usb_hcd.localmem_pool is used.
388 */390 */
389 struct dma_pool *td_cache;391 struct dma_pool *td_cache;
390 struct dma_pool *ed_cache;392 struct dma_pool *ed_cache;
include/linux/usb/hcd.h+5−0
@@ -216,6 +216,9 @@ struct usb_hcd { · 215 unmodified lines
216#define HC_IS_RUNNING(state) ((state) & __ACTIVE)216#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
217#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)217#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
218 218
219 /* memory pool for HCs having local memory, or %NULL */
220 struct gen_pool *localmem_pool;
221
219 /* more shared queuing code would be good; it should support222 /* more shared queuing code would be good; it should support
220 * smarter scheduling, handle transaction translators, etc;223 * smarter scheduling, handle transaction translators, etc;
221 * input size of periodic table to an interrupt scheduler.224 * 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
461 unsigned int irqnum, unsigned long irqflags);464 unsigned int irqnum, unsigned long irqflags);
462extern void usb_remove_hcd(struct usb_hcd *hcd);465extern void usb_remove_hcd(struct usb_hcd *hcd);
463extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);466extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
467int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
468 dma_addr_t dma, size_t size);
464 469
465struct platform_device;470struct platform_device;
466extern void usb_hcd_platform_shutdown(struct platform_device *dev);471extern 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