Hi, Pandita, Vikram a écrit : > >> -----Original Message----- >> From: Felipe Balbi [mailto:felipe.balbi@xxxxxxxxx] >> Sent: Thursday, January 14, 2010 5:28 AM >> To: ext Matthieu CASTET >> Cc: Balbi Felipe (Nokia-D/Helsinki); Gupta, Ajay Kumar; Pandita, Vikram; matthieu castet; linux- >> usb@xxxxxxxxxxxxxxx; Alan Stern >> Subject: Re: [RFC] gadget ethernet dma align fix >> >> Hi, >> >> On Thu, Jan 14, 2010 at 09:40:43AM +0100, ext Matthieu CASTET wrote: >>> Do you know if it is related to the align patch ? >>> >>> May be it could be interesting to enable debug in ethernet gadget driver. >> yeah I can do that, but it seems to be related to this patch. On an >> older version of musb (rtl 1.4) which doesn't suffer badly from this, >> this script works fine. >> >> will run again and let's see what's going on. > > Not working: > with this alignment patch v3 [1] in g_ether, > ping does not go through for size >= 1471, as pointed out by Felipe and Ajay. > This needs to be root caused and obviously a problem with introducing memmove() in g-ether. > > Works fine: > With the alignment fix in the MUSB controller driver [2] rather than g-ether, > the problem with ping size >= 1471 is not observed. > I found the problem. I was on rx path were skb->len were wrong. I attach a new patch that fix the issue. Regards, Matthieu
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index f2d270b..5cd8320 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -273,4 +273,14 @@ static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) return true; } +/** + * gadget_dma32 - return true if we want buffer aligned on 32 bits (for dma) + * @gadget: the gadget in question + */ +static inline bool gadget_dma32(struct usb_gadget *gadget) +{ + if (gadget_is_musbhdrc(gadget)) + return true; + return false; +} #endif /* __GADGET_CHIPS_H */ diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 2fc02bd..bd90859 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -249,7 +249,12 @@ 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); + /* + * RX: Do not move data by IP_ALIGN: + * if your DMA controller cannot handle it + */ + if (!gadget_dma32(dev->gadget)) + skb_reserve(skb, NET_IP_ALIGN); req->buf = skb->data; req->length = size; @@ -282,6 +287,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) /* normal completion */ case 0: skb_put(skb, req->actual); + if (gadget_dma32(dev->gadget) && NET_IP_ALIGN) { + u8 *data = skb->data; + size_t len = skb_headlen(skb); + skb_reserve(skb, NET_IP_ALIGN); + memmove(skb->data, data, len); + } if (dev->unwrap) { unsigned long flags; @@ -573,6 +584,24 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, length = skb->len; } + + /* + * Align data to 32bit if the dma controller requires it + */ + if (gadget_dma32(dev->gadget)) { + unsigned long align = (unsigned long)skb->data & 3; + if (WARN_ON(skb_headroom(skb) < align)) { + dev_kfree_skb_any(skb); + goto drop; + } else if (align) { + u8 *data = skb->data; + size_t len = skb_headlen(skb); + skb->data -= align; + memmove(skb->data, data, len); + skb_set_tail_pointer(skb, len); + } + } + req->buf = skb->data; req->context = skb; req->complete = tx_complete;