Hi, I have a patch for the tulip card, works as expected for me (kernel 2.6.11) . Use "ip link set mtu 1504 dev eth1" to hardware device. //&ers, Jan Nelson Caballero wrote: >Hi to all, > >I'm new with Linux VLAN support and with Linux in >general... Last time I use it was a long time ago. >I been reading a lot about the support of VLAN in the >newest kernels and test it with succesful >results....until I send a "ping -s 1476 x.x.x.x" >packet. Yes MTU issues :-S >I'm using 2.6.5 and 2.6.8 kernels, but seems to me >that the patches for the drivers are for 2.4.x >kernels. Their is a way to patch the drivers *.c >files that comes with these new kernels? > >I even patched the 2.6.5 with a 3c59x patch I found in >a page: http://www.oneunified.net/support/linux.html > >debian:/usr/src/linux-2.6.5/drivers/net# patch 3c59x.c >3c59x-patch >patching file 3c59x.c >Hunk #1 succeeded at 329 (offset 21 lines). >Hunk #2 succeeded at 700 (offset 46 lines). >Hunk #3 succeeded at 728 (offset 46 lines). >Hunk #4 succeeded at 825 (offset 45 lines). >Hunk #5 FAILED at 894. >Hunk #6 succeeded at 1174 (offset 136 lines). >Hunk #7 succeeded at 1627 (offset 157 lines). >Hunk #8 succeeded at 1711 (offset 157 lines). >Hunk #9 succeeded at 1857 (offset 164 lines). >Hunk #10 succeeded at 2082 (offset 169 lines). >debian:/usr/src/linux-2.6.5/drivers/net# > >But it sends me an error on one of the Hunks. > >Can anyone help me with some information. >Best regards and thanks, > >Nelson > > > > >__________________________________ >Do you Yahoo!? >Yahoo! Small Business - Try our new resources site! >http://smallbusiness.yahoo.com/resources/ >_______________________________________________ >Vlan mailing list >Vlan@xxxxxxxxxxxxxxx >http://www.lanforge.com/mailman/listinfo/vlan > > > -------------- next part -------------- diff -Nru linux-2.6.11/drivers/net/tulip/21142.c linux-2.6.11-redbox-1.3/drivers/net/tulip/21142.c --- linux-2.6.11/drivers/net/tulip/21142.c Wed Mar 2 08:37:50 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/21142.c Thu Mar 3 08:03:00 2005 @@ -9,8 +9,6 @@ of the GNU General Public License, incorporated herein by reference. Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ */ diff -Nru linux-2.6.11/drivers/net/tulip/de2104x.c linux-2.6.11-redbox-1.3/drivers/net/tulip/de2104x.c --- linux-2.6.11/drivers/net/tulip/de2104x.c Wed Mar 2 08:38:19 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/de2104x.c Thu Mar 3 08:03:00 2005 @@ -28,8 +28,8 @@ */ #define DRV_NAME "de2104x" -#define DRV_VERSION "0.7" -#define DRV_RELDATE "Mar 17, 2004" +#define DRV_VERSION "0.8" +#define DRV_RELDATE "Feb 25, 2005" #include <linux/config.h> #include <linux/module.h> @@ -95,7 +95,7 @@ (CP)->tx_tail + (DE_TX_RING_SIZE - 1) - (CP)->tx_head : \ (CP)->tx_tail - (CP)->tx_head - 1) -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +#define PKT_BUF_SZ (512*3) /* Size of each temporary Rx buffer.*/ #define RX_OFFSET 2 #define DE_SETUP_SKB ((struct sk_buff *) 1) @@ -370,7 +370,7 @@ "%s: rx err, slot %d status 0x%x len %d\n", de->dev->name, rx_tail, status, len); - if ((status & 0x38000300) != 0x0300) { + if ((status & (0x38000000 | RxWholePkt)) != RxWholePkt) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (netif_msg_rx_err(de)) @@ -417,7 +417,9 @@ goto rx_next; } - if (unlikely((status & 0x38008300) != 0x0300)) { + if (unlikely((status & (0x38000000 | + RxDescErrorSummary | + RxWholePkt)) != RxWholePkt)) { de_rx_err_acct(de, rx_tail, status, len); goto rx_next; } diff -Nru linux-2.6.11/drivers/net/tulip/de4x5.c linux-2.6.11-redbox-1.3/drivers/net/tulip/de4x5.c --- linux-2.6.11/drivers/net/tulip/de4x5.c Wed Mar 2 08:37:31 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/de4x5.c Thu Mar 3 08:03:00 2005 @@ -440,7 +440,9 @@ 0.548 30-Aug-03 Big 2.6 cleanup. Ported to PCI/EISA probing and generic DMA APIs. Fixed DE425 support on Alpha. <maz@xxxxxxxxxxxxxxxxxxx> - ========================================================================= + 0.549 25-Feb-05 Include VLAN support + <jan@xxxxxxxxxx> +========================================================================= */ #include <linux/config.h> @@ -753,7 +755,7 @@ */ #define NUM_RX_DESC 8 /* Number of RX descriptors */ #define NUM_TX_DESC 32 /* Number of TX descriptors */ -#define RX_BUFF_SZ 1536 /* Power of 2 for kmalloc and */ +#define RX_BUFF_SZ (512*3) /* Power of 2 for kmalloc and */ /* Multiple of 4 for DC21040 */ /* Allows 512 byte alignment */ struct de4x5_desc { diff -Nru linux-2.6.11/drivers/net/tulip/interrupt.c linux-2.6.11-redbox-1.3/drivers/net/tulip/interrupt.c --- linux-2.6.11/drivers/net/tulip/interrupt.c Wed Mar 2 08:38:37 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/interrupt.c Mon Mar 28 23:55:37 2005 @@ -9,8 +9,13 @@ of the GNU General Public License, incorporated herein by reference. Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ + and ftp://download.intel.com/design/network/manuals/27807401.pdf + + Try to allways use correct mtu for a given application, if + vlan tagging are used; set mtu to 1504. Default mtu are 1500 + for standard frames and let this driver invalidate any packet + higher than selected mtu to make driver more robust against + attacks. */ @@ -55,7 +60,6 @@ 0x80BD0000, 0x80CF0000, 0x80DF0000, -// 0x80FF0000 /* RX time = 16, RX pkts = 7, CM = 1 */ 0x80F10000 /* RX time = 16, RX pkts = 0, CM = 1 */ }; #endif @@ -113,6 +117,8 @@ int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = *budget; int received = 0; + int max_packet_size_minus_crc = dev->mtu ? dev->mtu + ETH_HLEN : TULIP_MTU_MAX + ETH_HLEN; + if (!netif_running(dev)) goto done; @@ -144,7 +150,7 @@ /* 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 (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) break; @@ -152,11 +158,36 @@ 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) goto not_done; + + /* + 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 1514 exclusive crc (4 bytes) + for standard mtu 1500 ( 1500 + 6 + 6 + 2 ) + Anything higher than this is always invalid + regardless of RxLengthOver2047 bits + */ + + if ((status & (RxLengthOver2047 | + RxDescCRCError | + RxDescCollisionSeen | + RxDescRunt | + RxDescDescErr | + RxWholePkt)) != RxWholePkt + || pkt_len > max_packet_size_minus_crc ) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { + + - if ((status & 0x38008300) != 0x0300) { - if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) @@ -165,30 +196,21 @@ dev->name, status); tp->stats.rx_length_errors++; } - } else if (status & RxDescFatalErr) { - /* There was a fatal error. */ + } 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 (status & 0x0004) tp->stats.rx_frame_errors++; - if (status & 0x0002) tp->stats.rx_crc_errors++; - if (status & 0x0001) tp->stats.rx_fifo_errors++; + if (pkt_len > max_packet_size_minus_crc || + 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 /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak @@ -265,20 +287,20 @@ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION /* We use this simplistic scheme for IM. It's proven by - real life installations. We can have IM enabled + real life installations. We can have IM enabled continuesly but this would cause unnecessary latency. Unfortunely we can't use all the NET_RX_* feedback here. This would turn on IM for devices that is not contributing to backlog congestion with unnecessary latency. - We monitor the the device RX-ring and have: + We monitor the the device RX-ring and have: - HW Interrupt Mitigation either ON or OFF. + HW Interrupt Mitigation either ON or OFF. ON: More then 1 pkt received (per intr.) OR we are dropping - OFF: Only 1 pkt received + OFF: Only 1 pkt received - Note. We only use min and max (0, 15) settings from mit_table */ + Note. We only use min and max (0, 15) settings from mit_table */ if( tp->flags & HAS_INTR_MITIGATION) { @@ -365,22 +387,47 @@ int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; int received = 0; - + short max_packet_size_minus_crc = dev->mtu ? dev->mtu + ETH_HLEN : TULIP_MTU_MAX + ETH_HLEN; + if (tulip_debug > 4) printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, tp->rx_ring[entry].status); /* 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) { - /* Ingore earlier buffers. */ + + break; + + /* + 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 > max_packet_size_minus_crc ) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { + + /* Ignore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) printk(KERN_WARNING "%s: Oversized Ethernet frame " @@ -388,31 +435,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 (status & 0x0004) tp->stats.rx_frame_errors++; - if (status & 0x0002) tp->stats.rx_crc_errors++; - if (status & 0x0001) tp->stats.rx_fifo_errors++; + if (pkt_len > max_packet_size_minus_crc || + 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 - /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak @@ -601,7 +638,7 @@ if (status & 0x0C00) tp->stats.tx_carrier_errors++; if (status & 0x0200) tp->stats.tx_window_errors++; if (status & 0x0002) tp->stats.tx_fifo_errors++; - if ((status & 0x0080) && tp->full_duplex == 0) + if((status & 0x0080) && tp->full_duplex == 0) tp->stats.tx_heartbeat_errors++; } else { tp->stats.tx_bytes += diff -Nru linux-2.6.11/drivers/net/tulip/tulip.h linux-2.6.11-redbox-1.3/drivers/net/tulip/tulip.h --- linux-2.6.11/drivers/net/tulip/tulip.h Wed Mar 2 08:38:26 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/tulip.h Thu Mar 3 08:03:00 2005 @@ -8,9 +8,19 @@ of the GNU General Public License, incorporated herein by reference. Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html} - for more information on this driver, or visit the project - Web page at http://sourceforge.net/projects/tulip/ + Version Date + + 25-Feb-05 Include VLAN support, Label status bits field for + easy reading in rxcode. From Intel 21143 pdf: + ftp://download.intel.com/design/network/manuals/27807401.pdf + In 6.3.4.6 Fram Reception Status we can read + Frame too long allways set for packet > 1518 bytes. + Checking received bytes counter instead of this flag + solve the problem with mtu > 1500. + <jan@xxxxxxxxxx> + +========================================================================= */ #ifndef __NET_TULIP_H__ @@ -29,7 +39,7 @@ /* undefine, or define to various debugging levels (>4 == obscene levels) */ -#define TULIP_DEBUG 1 +/* #define TULIP_DEBUG 1 */ /* undefine USE_IO_OPS for MMIO, define for PIO */ #ifdef CONFIG_TULIP_MMIO @@ -195,8 +205,39 @@ enum desc_status_bits { DescOwned = 0x80000000, - RxDescFatalErr = 0x8000, - RxWholePkt = 0x0300, + + /* + 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 }; @@ -261,9 +302,22 @@ #define TX_RING_SIZE 32 #define RX_RING_SIZE 128 -#define MEDIA_MASK 31 +#define MEDIA_MASK 31 + + +/* Keep maintainer happy with old bufferalign + The old hardvired TL bitflag works with 1500 + + ethframe + crc (1518 octets) and lower value. + New status check included in this release, to + work around this problem and ignoring TL flag. + <jan@xxxxxxxxxx> + Some code from Willy Tarreau +*/ + -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ +#define PKT_BUF_SZ (512*3) /* Size of each temporary Rx buffer. */ +#define TULIP_MTU_MIN 68 +#define TULIP_MTU_MAX (PKT_BUF_SZ - 18) /* -(ethframe + crc) */ #define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */ diff -Nru linux-2.6.11/drivers/net/tulip/tulip_core.c linux-2.6.11-redbox-1.3/drivers/net/tulip/tulip_core.c --- linux-2.6.11/drivers/net/tulip/tulip_core.c Wed Mar 2 08:38:10 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/tulip_core.c Tue Mar 29 06:34:25 2005 @@ -18,11 +18,11 @@ #define DRV_NAME "tulip" #ifdef CONFIG_TULIP_NAPI -#define DRV_VERSION "1.1.13-NAPI" /* Keep at least for test */ +#define DRV_VERSION "1.1.14-NAPI" /* Keep at least for test */ #else -#define DRV_VERSION "1.1.13" +#define DRV_VERSION "1.1.14" #endif -#define DRV_RELDATE "May 11, 2002" +#define DRV_RELDATE "Feb 25, 2005" #include <linux/module.h> @@ -41,6 +41,8 @@ #include <asm/pbm.h> #endif +#define netdev_priv_tulip(a) ((struct tulip_private *)netdev_priv(a)) + static char version[] __devinitdata = "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -54,7 +56,9 @@ /* Used to pass the full-duplex flag, etc. */ static int full_duplex[MAX_UNITS]; static int options[MAX_UNITS]; -static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */ + +/* static int mtu[MAX_UNITS]; //Jumbo MTU for interfaces. +*/ /* The possible media types that can be set in options[] are: */ const char * const medianame[32] = { @@ -264,6 +268,16 @@ #ifdef CONFIG_NET_POLL_CONTROLLER static void poll_tulip(struct net_device *dev); #endif +static int change_mtu(struct net_device *dev, int new_mtu); + + +static int change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < TULIP_MTU_MIN) || (new_mtu > TULIP_MTU_MAX)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} static void tulip_set_power_state (struct tulip_private *tp, int sleep, int snooze) @@ -393,17 +407,25 @@ tp->cur_index = i; tp->nwayset = 0; - if (dev->if_port) { - if (tp->chip_id == DC21143 && - (tulip_media_cap[dev->if_port] & MediaIsMII)) { + + switch ( tp->chip_id ) { + + case DC21143: + if ( dev->if_port ) { /* Is this what we want ? JH */ + if (tulip_media_cap[dev->if_port] & MediaIsMII) { /* We must reset the media CSRs when we force-select MII mode. */ iowrite32(0x0000, ioaddr + CSR13); iowrite32(0x0000, ioaddr + CSR14); iowrite32(0x0008, ioaddr + CSR15); - } - tulip_select_media(dev, 1); - } else if (tp->chip_id == DC21142) { - if (tp->mii_cnt) { + } + tulip_select_media(dev, 1); + } else { + +/* This is old part of 21142, and share DC21143 code, selected by if_port. + Also MII transceiver status message depends on if_port and feels wrong in + this case. JH */ + + if (tp->mii_cnt) { tulip_select_media(dev, 1); if (tulip_debug > 1) printk(KERN_INFO "%s: Using MII transceiver %d, status " @@ -414,16 +436,23 @@ dev->if_port = 11; iowrite32(0x0000, ioaddr + CSR13); iowrite32(0x0000, ioaddr + CSR14); - } else + } else t21142_start_nway(dev); - } else if (tp->chip_id == PNIC2) { + } /* End of DC21143 & DC211142 */ + break; + + case PNIC2: /* for initial startup advertise 10/100 Full and Half */ tp->sym_advertise = 0x01E0; /* enable autonegotiate end interrupt */ iowrite32(ioread32(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5); iowrite32(ioread32(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7); pnic2_start_nway(dev); - } else if (tp->chip_id == LC82C168 && ! tp->medialock) { + break; + + case LC82C168: + + if ( ! tp->medialock) { if (tp->mii_cnt) { dev->if_port = 11; tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); @@ -438,27 +467,44 @@ iowrite32(0x0201B078, ioaddr + 0xB8); next_tick = 1*HZ; } - } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) - && ! tp->medialock) { + } + break; + + case MX98713: + case COMPEX9881: + if ( ! tp->medialock) { dev->if_port = 0; tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); - } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { + } + + case MX98715: + case MX98725: /* Provided by BOLO, Macronix - 12/10/1998. */ dev->if_port = 0; tp->csr6 = 0x01a80200; iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); iowrite32(0x11000 | ioread16(ioaddr + 0xa0), ioaddr + 0xa0); - } else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) { + break; + + case COMET: + case CONEXANT: /* Enable automatic Tx underrun recovery. */ iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); dev->if_port = tp->mii_cnt ? 11 : 0; tp->csr6 = 0x00040000; - } else if (tp->chip_id == AX88140) { + break; + + case AX88140: + tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; - } else + break; + + default: tulip_select_media(dev, 1); + } + /* Start the chip's Tx to process setup frame. */ tulip_stop_rxtx(tp); barrier(); @@ -839,10 +885,9 @@ static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct tulip_private *np = netdev_priv(dev); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pdev)); + strcpy(info->bus_info, pci_name(netdev_priv_tulip(dev)->pdev)); } static struct ethtool_ops ops = { @@ -1587,8 +1632,7 @@ tp->default_port = options[board_idx] & MEDIA_MASK; if ((options[board_idx] & FullDuplex) || full_duplex[board_idx] > 0) tp->full_duplex = 1; - if (mtu[board_idx] > 0) - dev->mtu = mtu[board_idx]; + } if (dev->mem_start & MEDIA_MASK) tp->default_port = dev->mem_start & MEDIA_MASK; @@ -1650,6 +1694,8 @@ #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_tulip; #endif + dev->change_mtu = &change_mtu; + SET_ETHTOOL_OPS(dev, &ops); if (register_netdev(dev)) diff -Nru linux-2.6.11/drivers/net/tulip/xircom_tulip_cb.c linux-2.6.11-redbox-1.3/drivers/net/tulip/xircom_tulip_cb.c --- linux-2.6.11/drivers/net/tulip/xircom_tulip_cb.c Wed Mar 2 08:37:49 2005 +++ linux-2.6.11-redbox-1.3/drivers/net/tulip/xircom_tulip_cb.c Thu Mar 3 08:03:00 2005 @@ -47,7 +47,9 @@ /* Used to pass the full-duplex flag, etc. */ static int full_duplex[MAX_UNITS]; static int options[MAX_UNITS]; -static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */ + +/* static int mtu[MAX_UNITS]; / Jumbo MTU for interfaces. +*/ /* Keep the ring sizes a power of two for efficiency. Making the Tx ring too large decreases the effectiveness of channel @@ -601,8 +603,9 @@ tp->default_port = options[board_idx] & 15; if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0) tp->full_duplex = 1; - if (mtu[board_idx] > 0) +/* if (mtu[board_idx] > 0) dev->mtu = mtu[board_idx]; +*/ } if (dev->mem_start) tp->default_port = dev->mem_start; @@ -1208,8 +1211,9 @@ struct xircom_private *tp = netdev_priv(dev); int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; - int work_done = 0; - + int received = 0; + int pkt_len; + if (xircom_debug > 4) printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry, tp->rx_ring[entry].status); @@ -1222,63 +1226,101 @@ tp->rx_ring[entry].status); if (--rx_work_limit < 0) break; - if ((status & 0x38008300) != 0x0300) { - if ((status & 0x38000300) != 0x0300) { - /* Ignore earlier buffers. */ - if ((status & 0xffff) != 0x7fff) { - if (xircom_debug > 1) - printk(KERN_WARNING "%s: Oversized Ethernet frame " - "spanned multiple buffers, status %8.8x!\n", - dev->name, status); - tp->stats.rx_length_errors++; - } - } else if (status & Rx0DescError) { - /* There was a fatal error. */ - if (xircom_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 & (Rx0Runt | Rx0HugeFrame)) tp->stats.rx_length_errors++; - if (status & Rx0CRCError) tp->stats.rx_crc_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 - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ - if (pkt_len < rx_copybreak - && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* 16 byte align the IP header */ + /* + 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 (xircom_debug > 1) + printk(KERN_WARNING "%s: Oversized Ethernet frame " + "spanned multiple buffers, status %8.8x!\n", + dev->name, status); + tp->stats.rx_length_errors++; + } + } else { + /* There was a fatal error. */ + if (xircom_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 (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 { + struct sk_buff *skb; + + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single_for_cpu(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1), - pkt_len, 0); - skb_put(skb, pkt_len); + eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail, + pkt_len, 0); + skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), - bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len); + memcpy(skb_put(skb, pkt_len), + tp->rx_buffers[entry].skb->tail, + pkt_len); #endif - work_done++; - } else { /* Pass up the skb already on the Rx ring. */ - skb_put(skb = tp->rx_skbuff[entry], pkt_len); - tp->rx_skbuff[entry] = NULL; - } - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; - tp->stats.rx_packets++; - tp->stats.rx_bytes += pkt_len; - } + pci_dma_sync_single_for_device(tp->pdev, + tp->rx_buffers[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); + } else { /* Pass up the skb already on the Rx ring. */ + char *temp = skb_put(skb = tp->rx_buffers[entry].skb, + pkt_len); + + pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, + PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + + tp->rx_buffers[entry].skb = NULL; + tp->rx_buffers[entry].mapping = 0; + } + skb->protocol = eth_type_trans(skb, dev); + + netif_receive_skb(skb); + + dev->last_rx = jiffies; + tp->stats.rx_packets++; + tp->stats.rx_bytes += pkt_len; + } + received++; + + entry = (++tp->cur_rx) % RX_RING_SIZE; + if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) + tulip_refill_rx(dev); + + } + + entry = (++tp->cur_rx) % RX_RING_SIZE; } @@ -1292,12 +1334,12 @@ break; skb->dev = dev; /* Mark as being used by this device. */ tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail); - work_done++; + received++; } tp->rx_ring[entry].status = Rx0DescOwned; } - return work_done; + return received; }