[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080807170635.GC10471@solarflare.com>
Date: Thu, 7 Aug 2008 18:06:36 +0100
From: Ben Hutchings <bhutchings@...arflare.com>
To: Marc Haber <mh+netdev@...schlus.de>
Cc: netdev@...r.kernel.org
Subject: Re: Need help with MCS7830 driver and 802.1q VLAN Tagging
Marc Haber wrote:
> Hi,
>
> I am having difficulties with the MCS7830 driver in recent Linux
> versions (last version I tried was 2.6.26.1, didn't try 2.6.26.2 yet).
> It looks like the MCS7830 has an issue which prevents VLAN tagged
> ethernet frames from being transmitted and/or received when the frame
> size is near the ethernet MTU.
>
> This behavior was known around the millennium for a lot of ethernet
> drivers (including tulip) drivers. The host OS does not know that the
> frame is destined to go out via a VLAN tagged interface and thus
> builds frames with a size of up to 1500 octets. Then the VLAN tag gets
> added, which results in a 1504 octet frame, which seems to be dropped
> either by the MCS7830 hardware or its driver.
[...]
This could be a general problem with USB Ethernet drivers, as usbnet.c
doesn't seem to take account of VLAN header overhead.
Does the following help?
Ben.
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 8463efb..d24d22e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -42,6 +42,7 @@
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
+#include <linux/if_vlan.h>
#define DRIVER_VERSION "22-Aug-2005"
@@ -226,7 +227,7 @@ EXPORT_SYMBOL_GPL(usbnet_skb_return);
static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
- int ll_mtu = new_mtu + net->hard_header_len;
+ int ll_mtu = new_mtu + VLAN_HLEN + net->hard_header_len;
int old_hard_mtu = dev->hard_mtu;
int old_rx_urb_size = dev->rx_urb_size;
@@ -237,7 +238,7 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
return -EDOM;
net->mtu = new_mtu;
- dev->hard_mtu = net->mtu + net->hard_header_len;
+ dev->hard_mtu = ll_mtu;
if (dev->rx_urb_size == old_hard_mtu) {
dev->rx_urb_size = dev->hard_mtu;
if (dev->rx_urb_size > old_rx_urb_size)
@@ -1173,7 +1174,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
/* rx and tx sides can use different message sizes;
* bind() should set rx_urb_size in that case.
*/
- dev->hard_mtu = net->mtu + net->hard_header_len;
+ dev->hard_mtu = net->mtu + VLAN_HLEN + net->hard_header_len;
#if 0
// dma_supported() is deeply broken on almost all architectures
// possible with some EHCI controllers
@@ -1208,8 +1209,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
strcpy(net->name, "wlan%d");
/* maybe the remote can't receive an Ethernet MTU */
- if (net->mtu > (dev->hard_mtu - net->hard_header_len))
- net->mtu = dev->hard_mtu - net->hard_header_len;
+ if (net->mtu > (dev->hard_mtu - VLAN_HLEN - net->hard_header_len))
+ net->mtu = dev->hard_mtu - VLAN_HLEN - net->hard_header_len;
} else if (!info->in || !info->out)
status = usbnet_get_endpoints (dev, udev);
else {
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists