Re: [RFC] gadget ethernet dma align fix

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux