On the latest version of MUSB, DMA is not working properly if the Data in the 
packet doesn't start at 32bit aligned address. This issue was found while using 
MUSB as g_ether. The basic ping does not work, if the data in the Ethernet  
packet does not start at 32bit aligned address.

To overcome this issue, we found one solution mentioned in the below patch. 
This patch moves data (skb->data) by 2 bytes backwards in ethernet packet, 
which is nothing but skb->head.

I want to know, if there are any better approaches to fix this issue.

Signed-off-by: Nilkesh Patra <nilkesh.pa...@ti.com>
---
 drivers/usb/gadget/u_ether.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 2fc02bd..432b1bd 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -249,7 +249,6 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, 
gfp_t gfp_flags)
         * but on at least one, checksumming fails otherwise.  Note:
         * RNDIS headers involve variable numbers of LE32 values.
         */
-       skb_reserve(skb, NET_IP_ALIGN);
 
        req->buf = skb->data;
        req->length = size;
@@ -500,6 +499,8 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
        unsigned long           flags;
        struct usb_ep           *in;
        u16                     cdc_filter;
+       int                     i = 0;
+
 
        spin_lock_irqsave(&dev->lock, flags);
        if (dev->port_usb) {
@@ -573,9 +574,6 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 
                length = skb->len;
        }
-       req->buf = skb->data;
-       req->context = skb;
-       req->complete = tx_complete;
 
        /* use zlp framing on tx for strict CDC-Ether conformance,
         * though any robust network rx path ignores extra padding.
@@ -585,6 +583,14 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
        if (!dev->zlp && (length % in->maxpacket) == 0)
                length++;
 
+       if ((int)skb->data & 0x2) {
+               skb_push(skb, 2);
+               for (i = 0; i < length; i++)
+                       skb->data[i] = skb->data[i+2];
+       }
+       req->buf = skb->data;
+       req->context = skb;
+       req->complete = tx_complete;
        req->length = length;
 
        /* throttle highspeed IRQ rate back slightly */
-- 
1.5.4.3
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to