* [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
@ 2003-12-09 15:06 Rask Ingemann Lambertsen
2003-12-09 16:45 ` Jeff Garzik
2003-12-09 17:28 ` Ben Greear
0 siblings, 2 replies; 10+ messages in thread
From: Rask Ingemann Lambertsen @ 2003-12-09 15:06 UTC (permalink / raw)
To: netdev; +Cc: jgarzik
[-- Attachment #1: Type: text/plain, Size: 421 bytes --]
Attached is a patch which enables jumbo frames on tulip based boards. It
makes it possible to set an MTU of up to 2025 bytes. However, testing
against an NE3200 board using 10base-2 shows assorted problems when going
above 2018 bytes (for frames without VLAN tags). The problems show up as
framing errors, bad CRCs and such (in both directions).
The patch is against 2.4.22-bk45.
--
Regards,
Rask Ingemann Lambertsen
[-- Attachment #2: tulip-mtu.patch --]
[-- Type: text/plain, Size: 6905 bytes --]
--- linux-2.4.22/drivers/net/tulip/tulip.h-orig Mon Dec 1 21:58:11 2003
+++ linux-2.4.22/drivers/net/tulip/tulip.h Mon Dec 1 22:09:14 2003
@@ -190,6 +190,12 @@ enum desc_status_bits {
DescOwned = 0x80000000,
RxDescFatalErr = 0x8000,
RxWholePkt = 0x0300,
+ RxError = (1 << 15),
+ RxErrLong = (1 << 7),
+ RxErrCRC = (1 << 1),
+ RxErrFIFO = (1 << 0),
+ RxErrRunt = (1 << 11),
+ RxErrFrame = (1 << 14),
};
@@ -347,6 +353,7 @@ struct tulip_private {
struct ring_info tx_buffers[TX_RING_SIZE];
/* The addresses of receive-in-place skbuffs. */
struct ring_info rx_buffers[RX_RING_SIZE];
+ uint rx_buf_sz;
u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */
int chip_id;
int revision;
--- linux-2.4.22/drivers/net/tulip/interrupt.c-orig Mon Dec 1 21:52:10 2003
+++ linux-2.4.22/drivers/net/tulip/interrupt.c Mon Dec 1 22:03:50 2003
@@ -74,11 +74,11 @@ int tulip_refill_rx(struct net_device *d
struct sk_buff *skb;
dma_addr_t mapping;
- skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = tp->rx_buffers[entry].skb = dev_alloc_skb(tp->rx_buf_sz);
if (skb == NULL)
break;
- mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ,
+ mapping = pci_map_single(tp->pdev, skb->tail, tp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].mapping = mapping;
@@ -122,13 +122,21 @@ static int tulip_rx(struct net_device *d
/* If we own the next entry, it is a new packet. Send it up. */
while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+ s32 status_hacked;
if (tulip_debug > 5)
printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
dev->name, entry, status);
if (--rx_work_limit < 0)
break;
- if ((status & 0x38008300) != 0x0300) {
+
+ /* Ugly Jumbo frame hack. Remove error flag on long frames. */
+ if ((status & (RxErrLong | RxErrCRC | RxErrFIFO | RxErrRunt | RxErrFrame)) == RxErrLong)
+ status_hacked = status & ~(RxError | RxErrLong);
+ else
+ status_hacked = status;
+
+ if (unlikely((status_hacked & 0x38008300) != 0x0300)) {
if ((status & 0x38000300) != 0x0300) {
/* Ingore earlier buffers. */
if ((status & 0xffff) != 0x7fff) {
@@ -154,15 +162,6 @@ static int tulip_rx(struct net_device *d
short pkt_len = ((status >> 16) & 0x7ff) - 4;
struct sk_buff *skb;
-#ifndef final_version
- if (pkt_len > 1518) {
- printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
- dev->name, pkt_len, pkt_len);
- pkt_len = 1518;
- tp->stats.rx_length_errors++;
- }
-#endif
-
#ifdef CONFIG_NET_HW_FLOWCONTROL
drop = atomic_read(&netdev_dropping);
if (drop)
@@ -203,7 +202,7 @@ static int tulip_rx(struct net_device *d
#endif
pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
- PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].skb = NULL;
tp->rx_buffers[entry].mapping = 0;
--- linux-2.4.22/drivers/net/tulip/tulip_core.c-orig Mon Dec 1 21:34:32 2003
+++ linux-2.4.22/drivers/net/tulip/tulip_core.c Mon Dec 1 22:10:53 2003
@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
@@ -60,11 +61,13 @@ const char * const medianame[32] = {
"","","","", "","","","", "","","","Transceiver reset",
};
+#define PKT_BUF_SZ_MAX 2047 /* Maximum Rx buffer size. */
+
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|| defined(__sparc_) || defined(__ia64__) \
|| defined(__sh__) || defined(__mips__) || defined(__SH5__)
-static int rx_copybreak = 1518;
+static int rx_copybreak = PKT_BUF_SZ_MAX;
#else
static int rx_copybreak = 100;
#endif
@@ -518,9 +521,7 @@ void tulip_xon(struct net_device *dev)
static int
tulip_open(struct net_device *dev)
{
-#ifdef CONFIG_NET_HW_FLOWCONTROL
struct tulip_private *tp = (struct tulip_private *)dev->priv;
-#endif
int retval;
MOD_INC_USE_COUNT;
@@ -529,6 +530,10 @@ tulip_open(struct net_device *dev)
return retval;
}
+ tp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+ if (tp->rx_buf_sz > PKT_BUF_SZ_MAX)
+ tp->rx_buf_sz = PKT_BUF_SZ_MAX;
+
tulip_init_ring (dev);
tulip_up (dev);
@@ -673,13 +678,13 @@ static void tulip_init_ring(struct net_d
for (i = 0; i < RX_RING_SIZE; i++) {
tp->rx_ring[i].status = 0x00000000;
- tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
+ tp->rx_ring[i].length = cpu_to_le32(tp->rx_buf_sz);
tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1));
tp->rx_buffers[i].skb = NULL;
tp->rx_buffers[i].mapping = 0;
}
/* Mark the last entry as wrapping the ring. */
- tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP);
+ tp->rx_ring[i-1].length = cpu_to_le32(tp->rx_buf_sz | DESC_RING_WRAP);
tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma);
for (i = 0; i < RX_RING_SIZE; i++) {
@@ -688,12 +693,12 @@ static void tulip_init_ring(struct net_d
/* Note the receive buffer must be longword aligned.
dev_alloc_skb() provides 16 byte alignment. But do *not*
use skb_reserve() to align the IP header! */
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ struct sk_buff *skb = dev_alloc_skb(tp->rx_buf_sz);
tp->rx_buffers[i].skb = skb;
if (skb == NULL)
break;
mapping = pci_map_single(tp->pdev, skb->tail,
- PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
tp->rx_buffers[i].mapping = mapping;
skb->dev = dev; /* Mark as being used by this device. */
tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
@@ -876,7 +881,7 @@ static int tulip_close (struct net_devic
tp->rx_ring[i].length = 0;
tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
if (skb) {
- pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ,
+ pci_unmap_single(tp->pdev, mapping, tp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
}
@@ -1321,6 +1326,18 @@ out:
}
#endif
+static int tulip_change_mtu (struct net_device *dev, int mtu)
+{
+ if (netif_running (dev))
+ return (-EBUSY);
+
+ if (mtu < 0 || mtu > PKT_BUF_SZ_MAX - VLAN_ETH_HLEN - 4)
+ return (-EINVAL);
+
+ dev->mtu = mtu;
+ return (0);
+}
+
static int __devinit tulip_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1727,6 +1744,7 @@ static int __devinit tulip_init_one (str
dev->get_stats = tulip_get_stats;
dev->do_ioctl = private_ioctl;
dev->set_multicast_list = set_rx_mode;
+ dev->change_mtu = tulip_change_mtu;
if (register_netdev(dev))
goto err_out_free_ring;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 15:06 [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames Rask Ingemann Lambertsen
@ 2003-12-09 16:45 ` Jeff Garzik
2003-12-09 21:32 ` Rask Ingemann Lambertsen
2003-12-13 17:29 ` Rask Ingemann Lambertsen
2003-12-09 17:28 ` Ben Greear
1 sibling, 2 replies; 10+ messages in thread
From: Jeff Garzik @ 2003-12-09 16:45 UTC (permalink / raw)
To: Rask Ingemann Lambertsen; +Cc: netdev
Two questions and a comment...
Would you split this into two patches? The first simply adds, and uses,
tp->rx_buf_sz. The second adds PKT_BUF_SZ_MAX and mtu-related changes.
Have you looked at Donald Becker's changes to tulip.c? He went through
most of his drivers and made the changes necessary to support larger
MTUs. IIRC his tulip.c changes (which should be easily translate-able
to 2.6.x tulip) were a bit more minimal than your patch, but still
served the purpose.
For the comment: I am curious why a VLAN_xxx constant is included in
the calculation of max MTU, in the ->change_mtu hook? IMO ->change_mtu
simply needs to bind the MTU to the min and max h/w limits. If
VLAN_ETH_HLEN ever figures into the calculations, those calculations
should occur elsewhere, not in ->change_mtu.
Thanks!
Jeff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 15:06 [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames Rask Ingemann Lambertsen
2003-12-09 16:45 ` Jeff Garzik
@ 2003-12-09 17:28 ` Ben Greear
1 sibling, 0 replies; 10+ messages in thread
From: Ben Greear @ 2003-12-09 17:28 UTC (permalink / raw)
To: Rask Ingemann Lambertsen; +Cc: netdev, jgarzik
Rask Ingemann Lambertsen wrote:
> Attached is a patch which enables jumbo frames on tulip based boards. It
> makes it possible to set an MTU of up to 2025 bytes. However, testing
> against an NE3200 board using 10base-2 shows assorted problems when going
> above 2018 bytes (for frames without VLAN tags). The problems show up as
> framing errors, bad CRCs and such (in both directions).
>
> The patch is against 2.4.22-bk45.
> +static int tulip_change_mtu (struct net_device *dev, int mtu)
> +{
> + if (netif_running (dev))
> + return (-EBUSY);
> +
> + if (mtu < 0 || mtu > PKT_BUF_SZ_MAX - VLAN_ETH_HLEN - 4)
> + return (-EINVAL);
I suppose you could let them ignore the VLAN_ETH_HLEN if you
really wanted to (in case they are not running VLANs).
But, this should work fine too.
--Ben
> +
> + dev->mtu = mtu;
> + return (0);
> +}
> +
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 16:45 ` Jeff Garzik
@ 2003-12-09 21:32 ` Rask Ingemann Lambertsen
2003-12-09 22:38 ` Ben Greear
2003-12-13 17:29 ` Rask Ingemann Lambertsen
1 sibling, 1 reply; 10+ messages in thread
From: Rask Ingemann Lambertsen @ 2003-12-09 21:32 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
On Tue, Dec 09, 2003 at 11:45:42AM -0500, Jeff Garzik wrote:
> Two questions and a comment...
>
> Would you split this into two patches? The first simply adds, and uses,
> tp->rx_buf_sz. The second adds PKT_BUF_SZ_MAX and mtu-related changes.
That sounds like a good idea. I'll do that.
I tried to find a good place in the private structure to add the rx_buf_sz
field. By good, I mean using the cache efficiently. Any comments about that?
> Have you looked at Donald Becker's changes to tulip.c? He went through
> most of his drivers and made the changes necessary to support larger
> MTUs. IIRC his tulip.c changes (which should be easily translate-able
> to 2.6.x tulip) were a bit more minimal than your patch, but still
> served the purpose.
I have not looked at this particular part of Becker's tulip.c. I'll have a
look at it.
> For the comment: I am curious why a VLAN_xxx constant is included in
> the calculation of max MTU, in the ->change_mtu hook?
This is to ensure that the receive buffers are large enough to hold a frame
of the requested MTU also when using VLAN tags.
> IMO ->change_mtu
> simply needs to bind the MTU to the min and max h/w limits. If
> VLAN_ETH_HLEN ever figures into the calculations, those calculations
> should occur elsewhere, not in ->change_mtu.
What do you propose? Do we need something like
int vlan_adjust_mtu (int mtu)
{
#ifdef CONFIG_VLANN_8021Q
return (mtu - VLAN_HLEN);
#else
return (mtu);
#endif
}
and
int foobar_change_mtu (struct net_device *dev, int mtu)
{
mtu = vlan_adjust_mtu (mtu);
/* check hardware limits. */
...
dev->mtu = mtu;
return (0);
}
? Ben, this would also keep you happy, right?
--
Regards,
Rask Ingemann Lambertsen
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 21:32 ` Rask Ingemann Lambertsen
@ 2003-12-09 22:38 ` Ben Greear
2003-12-09 23:40 ` Rask Ingemann Lambertsen
0 siblings, 1 reply; 10+ messages in thread
From: Ben Greear @ 2003-12-09 22:38 UTC (permalink / raw)
To: Rask Ingemann Lambertsen; +Cc: Jeff Garzik, netdev
Rask Ingemann Lambertsen wrote:
> What do you propose? Do we need something like
>
> int vlan_adjust_mtu (int mtu)
> {
> #ifdef CONFIG_VLANN_8021Q
> return (mtu - VLAN_HLEN);
> #else
> return (mtu);
> #endif
> }
>
> and
>
> int foobar_change_mtu (struct net_device *dev, int mtu)
> {
> mtu = vlan_adjust_mtu (mtu);
> /* check hardware limits. */
> ...
> dev->mtu = mtu;
> return (0);
> }
>
> ? Ben, this would also keep you happy, right?
I was thinking the check could be made run-time, but in reality, this is
a very minor detail. It may be better to just hard-code it like you
had it originally. I don't like the patch above, I'd rather see the
#ifdef when checking for the maximum hardware limit, if anywhere.
Thanks,
Ben
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 22:38 ` Ben Greear
@ 2003-12-09 23:40 ` Rask Ingemann Lambertsen
2003-12-19 14:32 ` Rask Ingemann Lambertsen
0 siblings, 1 reply; 10+ messages in thread
From: Rask Ingemann Lambertsen @ 2003-12-09 23:40 UTC (permalink / raw)
To: Ben Greear; +Cc: netdev
On Tue, 09 Dec 2003 14:38:01 -0800, Ben Greear wrote
> Rask Ingemann Lambertsen wrote:
>
> > What do you propose? Do we need something like
> >
> > int vlan_adjust_mtu (int mtu)
> > {
> > #ifdef CONFIG_VLANN_8021Q
> > return (mtu - VLAN_HLEN);
> > #else
> > return (mtu);
> > #endif
> > }
> I was thinking the check could be made run-time, but in reality,
> this is a very minor detail.
You could use something like
if (dev->priv_flags & IFF_802_1Q_VLAN)
return (mtu - VLAN_HLEN);
else
return (mtu);
but then you have a problem if the MTU is set to the maximum with VLAN
disabled and someone decides to enable VLAN on the device afterwards. A
possible solution would be to set NETIF_F_VLAN_CHALLENGED when VLAN_HLEN
extra bytes are not available.
That said, even checking CONFIG_VLAN_8021Q is probably flawed too, because
ideally, even when building a kernel without VLAN support, you should be able
to use the bridging support in a VLAN environment. IMHO. I mean, if this is
not the case, please remind me why we need VLAN patches in the first place
since setting an MTU of 1496 bytes works with every Ethernet board and driver.
> I don't like the patch above, I'd rather see the
> #ifdef when checking for the maximum hardware limit, if anywhere.
I was thinking that there could be other reasons than VLAN for reducing the
MTU and that vlan_adjust_mtu() could take these into account as well. PPPoE
comes to my mind, but I have no clue how that is implemented in Linux (or any
other system).
--
Regards,
Rask Ingemann Lambertsen
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 16:45 ` Jeff Garzik
2003-12-09 21:32 ` Rask Ingemann Lambertsen
@ 2003-12-13 17:29 ` Rask Ingemann Lambertsen
2004-05-27 19:29 ` Ben Greear
1 sibling, 1 reply; 10+ messages in thread
From: Rask Ingemann Lambertsen @ 2003-12-13 17:29 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: Type: text/plain, Size: 984 bytes --]
On Tue, Dec 09, 2003 at 11:45:42AM -0500, Jeff Garzik wrote:
> Two questions and a comment...
>
> Would you split this into two patches? The first simply adds, and uses,
> tp->rx_buf_sz. The second adds PKT_BUF_SZ_MAX and mtu-related changes.
The first patch is attached to this message. I'm not happy with the second
part yet because it is too hackish and I would prefer to have a look at the
tulip documentation first.
> Have you looked at Donald Becker's changes to tulip.c? He went through
> most of his drivers and made the changes necessary to support larger
> MTUs. IIRC his tulip.c changes (which should be easily translate-able
> to 2.6.x tulip) were a bit more minimal than your patch, but still
> served the purpose.
I've just tested Becker's tulip.c v0.97 (7/22/2003) and it fails to receive
packets larger than the standard 1514 bytes. "ping -s 1472" works while
"ping -s 1473" doesn't (when pinging from another box).
--
Regards,
Rask Ingemann Lambertsen
[-- Attachment #2: tulip-rxbufsz.patch --]
[-- Type: text/plain, Size: 3704 bytes --]
--- linux-2.4.22/drivers/net/tulip/tulip.h-orig Mon Dec 1 21:58:11 2003
+++ linux-2.4.22/drivers/net/tulip/tulip.h Mon Dec 1 22:09:14 2003
@@ -347,6 +353,7 @@ struct tulip_private {
struct ring_info tx_buffers[TX_RING_SIZE];
/* The addresses of receive-in-place skbuffs. */
struct ring_info rx_buffers[RX_RING_SIZE];
+ uint rx_buf_sz;
u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */
int chip_id;
int revision;
--- linux-2.4.22/drivers/net/tulip/interrupt.c-orig Mon Dec 1 21:52:10 2003
+++ linux-2.4.22/drivers/net/tulip/interrupt.c Mon Dec 1 22:03:50 2003
@@ -74,11 +74,11 @@ int tulip_refill_rx(struct net_device *d
struct sk_buff *skb;
dma_addr_t mapping;
- skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = tp->rx_buffers[entry].skb = dev_alloc_skb(tp->rx_buf_sz);
if (skb == NULL)
break;
- mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ,
+ mapping = pci_map_single(tp->pdev, skb->tail, tp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].mapping = mapping;
@@ -203,7 +202,7 @@ static int tulip_rx(struct net_device *d
#endif
pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
- PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].skb = NULL;
tp->rx_buffers[entry].mapping = 0;
--- linux-2.4.22/drivers/net/tulip/tulip_core.c-orig Mon Dec 1 21:34:32 2003
+++ linux-2.4.22/drivers/net/tulip/tulip_core.c Mon Dec 1 22:10:53 2003
@@ -518,9 +521,7 @@ void tulip_xon(struct net_device *dev)
static int
tulip_open(struct net_device *dev)
{
-#ifdef CONFIG_NET_HW_FLOWCONTROL
struct tulip_private *tp = (struct tulip_private *)dev->priv;
-#endif
int retval;
MOD_INC_USE_COUNT;
@@ -529,6 +530,7 @@ tulip_open(struct net_device *dev)
return retval;
}
+ tp->rx_buf_sz = PKT_BUF_SZ;
tulip_init_ring (dev);
tulip_up (dev);
@@ -673,13 +678,13 @@ static void tulip_init_ring(struct net_d
for (i = 0; i < RX_RING_SIZE; i++) {
tp->rx_ring[i].status = 0x00000000;
- tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
+ tp->rx_ring[i].length = cpu_to_le32(tp->rx_buf_sz);
tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1));
tp->rx_buffers[i].skb = NULL;
tp->rx_buffers[i].mapping = 0;
}
/* Mark the last entry as wrapping the ring. */
- tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP);
+ tp->rx_ring[i-1].length = cpu_to_le32(tp->rx_buf_sz | DESC_RING_WRAP);
tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma);
for (i = 0; i < RX_RING_SIZE; i++) {
@@ -688,12 +693,12 @@ static void tulip_init_ring(struct net_d
/* Note the receive buffer must be longword aligned.
dev_alloc_skb() provides 16 byte alignment. But do *not*
use skb_reserve() to align the IP header! */
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ struct sk_buff *skb = dev_alloc_skb(tp->rx_buf_sz);
tp->rx_buffers[i].skb = skb;
if (skb == NULL)
break;
mapping = pci_map_single(tp->pdev, skb->tail,
- PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
tp->rx_buffers[i].mapping = mapping;
skb->dev = dev; /* Mark as being used by this device. */
tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
@@ -876,7 +881,7 @@ static int tulip_close (struct net_devic
tp->rx_ring[i].length = 0;
tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
if (skb) {
- pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ,
+ pci_unmap_single(tp->pdev, mapping, tp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-09 23:40 ` Rask Ingemann Lambertsen
@ 2003-12-19 14:32 ` Rask Ingemann Lambertsen
2003-12-20 6:22 ` Ben Greear
0 siblings, 1 reply; 10+ messages in thread
From: Rask Ingemann Lambertsen @ 2003-12-19 14:32 UTC (permalink / raw)
To: Ben Greear; +Cc: netdev, jgarzik
On Wed, Dec 10, 2003 at 12:40:02AM +0100, Rask Ingemann Lambertsen wrote:
> That said, even checking CONFIG_VLAN_8021Q is probably flawed too, because
> ideally, even when building a kernel without VLAN support, you should be able
> to use the bridging support in a VLAN environment. IMHO. I mean, if this is
> not the case, please remind me why we need VLAN patches in the first place
> since setting an MTU of 1496 bytes works with every Ethernet board and driver.
Further, why is it not the responsibility of vconfig to ensure that the MTU
of the VLAN device is 4 lower than that of the underlying, "bare" Ethernet
device?
--
Regards,
Rask Ingemann Lambertsen
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-19 14:32 ` Rask Ingemann Lambertsen
@ 2003-12-20 6:22 ` Ben Greear
0 siblings, 0 replies; 10+ messages in thread
From: Ben Greear @ 2003-12-20 6:22 UTC (permalink / raw)
To: Rask Ingemann Lambertsen; +Cc: netdev, jgarzik
Rask Ingemann Lambertsen wrote:
> On Wed, Dec 10, 2003 at 12:40:02AM +0100, Rask Ingemann Lambertsen wrote:
>
>
>>That said, even checking CONFIG_VLAN_8021Q is probably flawed too, because
>>ideally, even when building a kernel without VLAN support, you should be able
>>to use the bridging support in a VLAN environment. IMHO. I mean, if this is
>>not the case, please remind me why we need VLAN patches in the first place
>>since setting an MTU of 1496 bytes works with every Ethernet board and driver.
>
>
> Further, why is it not the responsibility of vconfig to ensure that the MTU
> of the VLAN device is 4 lower than that of the underlying, "bare" Ethernet
> device?
Because correctly patched drivers can have eth0 with MTU 1500 and vlan eth0.5 with
MTU of 1500 as well. I do not want to add artificial policy in vconfig or the
kernel,though of course users can hack up the MTU settings manually as
desired...
Ben
--
Ben Greear <greearb@candelatech.com> <Ben_Greear@excite.com>
President of Candela Technologies Inc http://www.candelatech.com
ScryMUD: http://scry.wanfear.com http://scry.wanfear.com/~greear
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames
2003-12-13 17:29 ` Rask Ingemann Lambertsen
@ 2004-05-27 19:29 ` Ben Greear
0 siblings, 0 replies; 10+ messages in thread
From: Ben Greear @ 2004-05-27 19:29 UTC (permalink / raw)
To: Rask Ingemann Lambertsen; +Cc: Jeff Garzik, netdev, Linux 802.1Q VLAN
Rask Ingemann Lambertsen wrote:
> On Tue, Dec 09, 2003 at 11:45:42AM -0500, Jeff Garzik wrote:
>
>>Two questions and a comment...
>>
>>Would you split this into two patches? The first simply adds, and uses,
>>tp->rx_buf_sz. The second adds PKT_BUF_SZ_MAX and mtu-related changes.
>
>
> The first patch is attached to this message. I'm not happy with the second
> part yet because it is too hackish and I would prefer to have a look at the
> tulip documentation first.
Whatever became of this? For what it's worth, I have been using
a patch originally by Ben McKeegan that seems to work fine. But,
I'd be happy for either of the patches to go in so long as we can finally
get the tulip driver to work with VLANs.
--- linux-2.4.25/drivers/net/tulip/interrupt.c 2003-06-13 07:51:35.000000000 -0700
+++ linux-2.4.25.p4/drivers/net/tulip/interrupt.c 2004-05-24 17:24:26.000000000 -0700
@@ -1,4 +1,4 @@
-/*
+/* -*-linux-c-*-
drivers/net/tulip/interrupt.c
Maintained by Jeff Garzik <jgarzik@pobox.com>
@@ -122,14 +122,34 @@
/* If we own the next entry, it is a new packet. Send it up. */
while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
s32 status = le32_to_cpu(tp->rx_ring[entry].status);
-
+ short pkt_len;
+
if (tulip_debug > 5)
printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
dev->name, entry, status);
if (--rx_work_limit < 0)
break;
- if ((status & 0x38008300) != 0x0300) {
- if ((status & 0x38000300) != 0x0300) {
+ /*
+ Omit the four octet CRC from the length.
+ (May not be considered valid until we have
+ checked status for RxLengthOver2047 bits)
+ */
+ pkt_len = ((status >> 16) & 0x7ff) - 4;
+
+ /*
+ Maximum pkt_len is 1518 (1514 + vlan header)
+ Anything higher than this is always invalid
+ regardless of RxLengthOver2047 bits
+ */
+
+ if (((status & (RxLengthOver2047 |
+ RxDescCRCError |
+ RxDescCollisionSeen |
+ RxDescRunt |
+ RxDescDescErr |
+ RxWholePkt)) != RxWholePkt)
+ || (pkt_len > 1518) ) {
+ if ((status & (RxLengthOver2047 | RxWholePkt)) != RxWholePkt) {
/* Ingore earlier buffers. */
if ((status & 0xffff) != 0x7fff) {
if (tulip_debug > 1)
@@ -138,31 +158,21 @@
dev->name, status);
tp->stats.rx_length_errors++;
}
- } else if (status & RxDescFatalErr) {
+ } else {
/* There was a fatal error. */
if (tulip_debug > 2)
printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
dev->name, status);
tp->stats.rx_errors++; /* end of a packet.*/
- if (status & 0x0890) tp->stats.rx_length_errors++;
+ if ((pkt_len > 1518) || (status & RxDescRunt))
+ tp->stats.rx_length_errors++;
if (status & 0x0004) tp->stats.rx_frame_errors++;
if (status & 0x0002) tp->stats.rx_crc_errors++;
if (status & 0x0001) tp->stats.rx_fifo_errors++;
}
} else {
- /* Omit the four octet CRC from the length. */
- short pkt_len = ((status >> 16) & 0x7ff) - 4;
struct sk_buff *skb;
-#ifndef final_version
- if (pkt_len > 1518) {
- printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
- dev->name, pkt_len, pkt_len);
- pkt_len = 1518;
- tp->stats.rx_length_errors++;
- }
-#endif
-
#ifdef CONFIG_NET_HW_FLOWCONTROL
drop = atomic_read(&netdev_dropping);
if (drop)
--- linux-2.4.25/drivers/net/tulip/tulip.h 2002-11-28 15:53:14.000000000 -0800
+++ linux-2.4.25.p4/drivers/net/tulip/tulip.h 2004-05-24 17:29:48.000000000 -0700
@@ -188,8 +188,40 @@
enum desc_status_bits {
DescOwned = 0x80000000,
- RxDescFatalErr = 0x8000,
+
+ /*
+ Error summary flag is logical or of 'CRC Error',
+ 'Collision Seen', 'Frame Too Long', 'Runt' and
+ 'Descriptor Error' flags generated within tulip chip.
+ */
+ RxDescErrorSummary = 0x8000,
+
+ RxDescCRCError = 0x0002,
+ RxDescCollisionSeen = 0x0040,
+
+ /*
+ 'Frame Too Long' flag is set if packet length including CRC
+ exceeds 1518. However, a full sized VLAN tagged frame is
+ 1522 bytes including CRC.
+
+ The tulip chip does not block oversized frames, and if this
+ flag is set on a receive descriptor it does not indicate
+ the frame has been truncated. The receive descriptor also
+ includes the actual length. Therefore we can safety ignore
+ this flag and check the length ourselves.
+ */
+ RxDescFrameTooLong = 0x0080,
+ RxDescRunt = 0x0800,
+ RxDescDescErr = 0x4000,
RxWholePkt = 0x0300,
+
+ /*
+ Top three bits of 14 bit frame length (status bits 27-29)
+ should never be set as that would make frame over 2047 bytes.
+ The Receive Watchdog flag (bit 4) may indicate the length is
+ over 2048 and the length field is invalid.
+ */
+ RxLengthOver2047 = 0x38000010
};
>
>
>>Have you looked at Donald Becker's changes to tulip.c? He went through
>>most of his drivers and made the changes necessary to support larger
>>MTUs. IIRC his tulip.c changes (which should be easily translate-able
>>to 2.6.x tulip) were a bit more minimal than your patch, but still
>>served the purpose.
>
>
> I've just tested Becker's tulip.c v0.97 (7/22/2003) and it fails to receive
> packets larger than the standard 1514 bytes. "ping -s 1472" works while
> "ping -s 1473" doesn't (when pinging from another box).
>
>
>
> ------------------------------------------------------------------------
>
> --- linux-2.4.22/drivers/net/tulip/tulip.h-orig Mon Dec 1 21:58:11 2003
> +++ linux-2.4.22/drivers/net/tulip/tulip.h Mon Dec 1 22:09:14 2003
> @@ -347,6 +353,7 @@ struct tulip_private {
> struct ring_info tx_buffers[TX_RING_SIZE];
> /* The addresses of receive-in-place skbuffs. */
> struct ring_info rx_buffers[RX_RING_SIZE];
> + uint rx_buf_sz;
> u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */
> int chip_id;
> int revision;
> --- linux-2.4.22/drivers/net/tulip/interrupt.c-orig Mon Dec 1 21:52:10 2003
> +++ linux-2.4.22/drivers/net/tulip/interrupt.c Mon Dec 1 22:03:50 2003
> @@ -74,11 +74,11 @@ int tulip_refill_rx(struct net_device *d
> struct sk_buff *skb;
> dma_addr_t mapping;
>
> - skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
> + skb = tp->rx_buffers[entry].skb = dev_alloc_skb(tp->rx_buf_sz);
> if (skb == NULL)
> break;
>
> - mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ,
> + mapping = pci_map_single(tp->pdev, skb->tail, tp->rx_buf_sz,
> PCI_DMA_FROMDEVICE);
> tp->rx_buffers[entry].mapping = mapping;
>
> @@ -203,7 +202,7 @@ static int tulip_rx(struct net_device *d
> #endif
>
> pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
> - PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
> + tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
>
> tp->rx_buffers[entry].skb = NULL;
> tp->rx_buffers[entry].mapping = 0;
> --- linux-2.4.22/drivers/net/tulip/tulip_core.c-orig Mon Dec 1 21:34:32 2003
> +++ linux-2.4.22/drivers/net/tulip/tulip_core.c Mon Dec 1 22:10:53 2003
> @@ -518,9 +521,7 @@ void tulip_xon(struct net_device *dev)
> static int
> tulip_open(struct net_device *dev)
> {
> -#ifdef CONFIG_NET_HW_FLOWCONTROL
> struct tulip_private *tp = (struct tulip_private *)dev->priv;
> -#endif
> int retval;
> MOD_INC_USE_COUNT;
>
> @@ -529,6 +530,7 @@ tulip_open(struct net_device *dev)
> return retval;
> }
>
> + tp->rx_buf_sz = PKT_BUF_SZ;
> tulip_init_ring (dev);
>
> tulip_up (dev);
> @@ -673,13 +678,13 @@ static void tulip_init_ring(struct net_d
>
> for (i = 0; i < RX_RING_SIZE; i++) {
> tp->rx_ring[i].status = 0x00000000;
> - tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
> + tp->rx_ring[i].length = cpu_to_le32(tp->rx_buf_sz);
> tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1));
> tp->rx_buffers[i].skb = NULL;
> tp->rx_buffers[i].mapping = 0;
> }
> /* Mark the last entry as wrapping the ring. */
> - tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP);
> + tp->rx_ring[i-1].length = cpu_to_le32(tp->rx_buf_sz | DESC_RING_WRAP);
> tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma);
>
> for (i = 0; i < RX_RING_SIZE; i++) {
> @@ -688,12 +693,12 @@ static void tulip_init_ring(struct net_d
> /* Note the receive buffer must be longword aligned.
> dev_alloc_skb() provides 16 byte alignment. But do *not*
> use skb_reserve() to align the IP header! */
> - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
> + struct sk_buff *skb = dev_alloc_skb(tp->rx_buf_sz);
> tp->rx_buffers[i].skb = skb;
> if (skb == NULL)
> break;
> mapping = pci_map_single(tp->pdev, skb->tail,
> - PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
> + tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
> tp->rx_buffers[i].mapping = mapping;
> skb->dev = dev; /* Mark as being used by this device. */
> tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
> @@ -876,7 +881,7 @@ static int tulip_close (struct net_devic
> tp->rx_ring[i].length = 0;
> tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
> if (skb) {
> - pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ,
> + pci_unmap_single(tp->pdev, mapping, tp->rx_buf_sz,
> PCI_DMA_FROMDEVICE);
> dev_kfree_skb (skb);
> }
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2004-05-27 19:29 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-09 15:06 [EXPERIMENTAL PATCH] 2.4 tulip jumbo frames Rask Ingemann Lambertsen
2003-12-09 16:45 ` Jeff Garzik
2003-12-09 21:32 ` Rask Ingemann Lambertsen
2003-12-09 22:38 ` Ben Greear
2003-12-09 23:40 ` Rask Ingemann Lambertsen
2003-12-19 14:32 ` Rask Ingemann Lambertsen
2003-12-20 6:22 ` Ben Greear
2003-12-13 17:29 ` Rask Ingemann Lambertsen
2004-05-27 19:29 ` Ben Greear
2003-12-09 17:28 ` Ben Greear
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).