From 6dfb7bff0f0da151f93f716038269f3c1fd3745d Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Mon, 7 Nov 2011 16:37:31 +0530 Subject: ux500:USB:Updating is_compatible with class checks Current checks in is_compatible doesn't handle all the needed DMA cases. In case of Ethernet out transactions data size is not known and we cannot use the dma effectively in such cases. So,Using class names to accurately handle all the musb dma limitations/features.Hence, only for mass storage and ACM classes, data will be transfered over DMA. ST-Ericsson Linux next: NA ST-Ericsson ID: 373086 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: If83db00286bdc04c3d8e65e272b3ed586390ecfb Signed-off-by: Sakethram Bommisetti Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36991 Reviewed-by: Praveena NADAHALLY Reviewed-by: Rabin VINCENT --- drivers/usb/musb/ux500_dma.c | 50 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 389bf8890a5..cb86beb8ec2 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -32,6 +32,11 @@ #include #include #include "musb_core.h" +#undef DBG +#undef WARNING +#undef INFO +#include +#define U8500_USB_DMA_MIN_TRANSFER_SIZE 512 struct ux500_dma_channel { struct dma_channel channel; @@ -205,13 +210,44 @@ static void ux500_dma_channel_release(struct dma_channel *channel) static int ux500_dma_is_compatible(struct dma_channel *channel, u16 maxpacket, void *buf, u32 length) { - if ((maxpacket & 0x3) || - ((int)buf & 0x3) || - (length < 512) || - (length & 0x3)) - return false; - else - return true; + struct ux500_dma_channel *ux500_channel = channel->private_data; + struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; + struct musb *musb = hw_ep->musb; + struct usb_descriptor_header **descriptors; + struct usb_function *f; + struct usb_gadget *gadget = &musb->g; + struct usb_composite_dev *cdev = get_gadget_data(gadget); + + if (length < U8500_USB_DMA_MIN_TRANSFER_SIZE) + return 0; + + list_for_each_entry(f, &cdev->config->functions, list) { + if (!strcmp(f->name, "cdc_ethernet") || + !strcmp(f->name, "rndis") || + !strcmp(f->name, "phonet") || + !strcmp(f->name, "adb")) { + if (gadget->speed == USB_SPEED_HIGH) + descriptors = f->hs_descriptors; + else + descriptors = f->descriptors; + + for (; *descriptors; ++descriptors) { + struct usb_endpoint_descriptor *ep; + + if ((*descriptors)->bDescriptorType != + USB_DT_ENDPOINT) + continue; + + ep = (struct usb_endpoint_descriptor *) + *descriptors; + if (ep->bEndpointAddress == + ux500_channel->hw_ep->epnum) + return 0; + } + } + } + + return 1; } /** -- cgit v1.2.3