diff options
author | ZCHLABB47624-01 <b47624@b47624.ap.freescale.net> | 2014-05-15 18:50:30 +0800 |
---|---|---|
committer | Peng Fushi <fushi.peng@freescale.com> | 2014-08-29 14:30:36 +0800 |
commit | e314064d431d32a5a81da6681f57cdb3c20cad5b (patch) | |
tree | fc771d02c1c4d04de8ad3efd0b6ca6c222183903 | |
parent | dec81b660c750177ed8907cf0ff12d8e55e2abb2 (diff) |
ENGR00313729 usb: class: acm: use nonbufferable memory for rx dma buffer
use dma_pool_alloc_nonbufferable for rx buf instead of dma_alloc_coherent
for usb host cdc-acm to fix data coherent issue.
Signed-off-by: Li Jun <b47624@freescale.com>
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/buffer.c | 25 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 9 | ||||
-rw-r--r-- | include/linux/usb.h | 2 | ||||
-rw-r--r-- | include/linux/usb/hcd.h | 2 |
5 files changed, 40 insertions, 2 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 84e69ea2309b..5a97ff143fc3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1134,8 +1134,8 @@ made_compressed_probe: struct acm_rb *rb = &(acm->read_buffers[i]); struct urb *urb; - rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, - &rb->dma); + rb->base = usb_alloc_nonbufferable(acm->dev, readsize, + GFP_KERNEL, &rb->dma); if (!rb->base) { dev_err(&intf->dev, "out of memory " "(read bufs usb_alloc_coherent)\n"); diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index b0585e623ba9..687ddb897ed8 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -122,6 +122,31 @@ void *hcd_buffer_alloc( return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags); } +void *hcd_buffer_alloc_nonbufferable( + struct usb_bus *bus, + size_t size, + gfp_t mem_flags, + dma_addr_t *dma +) +{ + struct usb_hcd *hcd = bus_to_hcd(bus); + int i; + + /* some USB hosts just use PIO */ + if (!bus->controller->dma_mask && + !(hcd->driver->flags & HCD_LOCAL_MEM)) { + *dma = ~(dma_addr_t) 0; + return kmalloc(size, mem_flags); + } + + for (i = 0; i < HCD_BUFFER_POOLS; i++) { + if (size <= pool_max[i]) + return dma_pool_alloc_nonbufferable(hcd->pool[i], + mem_flags, dma); + } + return NULL; +} + void hcd_buffer_free( struct usb_bus *bus, size_t size, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 8706fc97e60f..0463fad320f2 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -682,6 +682,15 @@ void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, } EXPORT_SYMBOL_GPL(usb_alloc_coherent); +void *usb_alloc_nonbufferable(struct usb_device *dev, size_t size, + gfp_t mem_flags, dma_addr_t *dma) +{ + if (!dev || !dev->bus) + return NULL; + return hcd_buffer_alloc_nonbufferable(dev->bus, size, mem_flags, dma); +} +EXPORT_SYMBOL_GPL(usb_alloc_nonbufferable); + /** * usb_free_coherent - free memory allocated with usb_alloc_coherent() * @dev: device the buffer was used with diff --git a/include/linux/usb.h b/include/linux/usb.h index 6cd157629772..71997492f34a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1398,6 +1398,8 @@ static inline int usb_urb_dir_out(struct urb *urb) void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma); +void *usb_alloc_nonbufferable(struct usb_device *dev, size_t size, + gfp_t mem_flags, dma_addr_t *dma); void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index c0ecc5a2ef9e..fae56f96f0bc 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -405,6 +405,8 @@ void hcd_buffer_destroy(struct usb_hcd *hcd); void *hcd_buffer_alloc(struct usb_bus *bus, size_t size, gfp_t mem_flags, dma_addr_t *dma); +void *hcd_buffer_alloc_nonbufferable(struct usb_bus *bus, size_t size, + gfp_t mem_flags, dma_addr_t *dma); void hcd_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma); |