If the following environment, the first argument of DMA API should be set to a DMAC's device structure, not a udc controller's one. - A udc controller needs an external DMAC device (like a DMA Engine). - The external DMAC enables IOMMU. So, this patch add usb_gadget_{un}map_request_by_dev() API to set a DMAC's device structure by a udc controller driver. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> --- drivers/usb/gadget/udc/udc-core.c | 24 ++++++++++++++++++------ include/linux/usb/gadget.h | 4 ++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index c6e7646..6e8300d 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -61,11 +61,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, #ifdef CONFIG_HAS_DMA -int usb_gadget_map_request(struct usb_gadget *gadget, +int usb_gadget_map_request_by_dev(struct device *dev, struct usb_request *req, int is_in) { - struct device *dev = gadget->dev.parent; - if (req->length == 0) return 0; @@ -92,24 +90,38 @@ int usb_gadget_map_request(struct usb_gadget *gadget, return 0; } +EXPORT_SYMBOL_GPL(usb_gadget_map_request_by_dev); + +int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + return usb_gadget_map_request_by_dev(gadget->dev.parent, req, is_in); +} EXPORT_SYMBOL_GPL(usb_gadget_map_request); -void usb_gadget_unmap_request(struct usb_gadget *gadget, +void usb_gadget_unmap_request_by_dev(struct device *dev, struct usb_request *req, int is_in) { if (req->length == 0) return; if (req->num_mapped_sgs) { - dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs, + dma_unmap_sg(dev, req->sg, req->num_mapped_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->num_mapped_sgs = 0; } else { - dma_unmap_single(gadget->dev.parent, req->dma, req->length, + dma_unmap_single(dev, req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } } +EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev); + +void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + usb_gadget_unmap_request_by_dev(gadget->dev.parent, req, is_in); +} EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); #endif /* CONFIG_HAS_DMA */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 5d4e151..457651b 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1223,9 +1223,13 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget, /* utility to simplify map/unmap of usb_requests to/from DMA */ +extern int usb_gadget_map_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); extern int usb_gadget_map_request(struct usb_gadget *gadget, struct usb_request *req, int is_in); +extern void usb_gadget_unmap_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); extern void usb_gadget_unmap_request(struct usb_gadget *gadget, struct usb_request *req, int is_in); -- 1.9.1