diff options
Diffstat (limited to 'drivers/net/tulip')
-rw-r--r-- | drivers/net/tulip/de4x5.c | 7 | ||||
-rw-r--r-- | drivers/net/tulip/dmfe.c | 2 | ||||
-rw-r--r-- | drivers/net/tulip/interrupt.c | 94 | ||||
-rw-r--r-- | drivers/net/tulip/media.c | 8 | ||||
-rw-r--r-- | drivers/net/tulip/tulip.h | 32 | ||||
-rw-r--r-- | drivers/net/tulip/tulip_core.c | 45 | ||||
-rw-r--r-- | drivers/net/tulip/uli526x.c | 2 | ||||
-rw-r--r-- | drivers/net/tulip/winbond-840.c | 7 |
8 files changed, 133 insertions, 64 deletions
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 6418f74415d7..f9491bd787d1 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -479,7 +479,8 @@ #include "de4x5.h" -static char version[] __devinitdata = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n"; +static const char version[] __devinitconst = + KERN_INFO "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n"; #define c_char const char @@ -3941,8 +3942,8 @@ PCI_signature(char *name, struct de4x5_private *lp) strcpy(name, "DE434/5"); return status; } else { /* Search for a DEC name in the SROM */ - int i = *((char *)&lp->srom + 19) * 3; - strncpy(name, (char *)&lp->srom + 26 + i, 8); + int tmp = *((char *)&lp->srom + 19) * 3; + strncpy(name, (char *)&lp->srom + 26 + tmp, 8); } name[8] = '\0'; for (i=0; i<siglen; i++) { diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 2e5c99941f35..e2c9d0f5a755 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -288,7 +288,7 @@ enum dmfe_CR6_bits { /* Global variable declaration ----------------------------- */ static int __devinitdata printed_version; -static char version[] __devinitdata = +static const char version[] __devinitconst = KERN_INFO DRV_NAME ": Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")\n"; diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 6c3428a37c0b..c8d220cf2cce 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -103,7 +103,7 @@ void oom_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); } int tulip_poll(struct napi_struct *napi, int budget) @@ -140,6 +140,7 @@ int tulip_poll(struct napi_struct *napi, int budget) /* 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; @@ -151,8 +152,28 @@ int tulip_poll(struct napi_struct *napi, int budget) if (++work_done >= budget) goto not_done; - 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) @@ -161,30 +182,23 @@ int tulip_poll(struct napi_struct *napi, int budget) 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 /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak @@ -300,7 +314,7 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Remove us from polling list and enable RX intr. */ - netif_rx_complete(napi); + napi_complete(napi); iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); /* The last op happens after poll completion. Which means the following: @@ -333,10 +347,10 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Think: timer_pending() was an explicit signature of bug. * Timer can be pending now but fired and completed - * before we did netif_rx_complete(). See? We would lose it. */ + * before we did napi_complete(). See? We would lose it. */ /* remove ourselves from the polling list */ - netif_rx_complete(napi); + napi_complete(napi); return work_done; } @@ -356,14 +370,35 @@ static int tulip_rx(struct net_device *dev) /* 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) @@ -372,31 +407,22 @@ static int tulip_rx(struct net_device *dev) 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 - /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak @@ -519,7 +545,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) rxd++; /* Mask RX intrs and add the device to poll list. */ iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) break; diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index 91cf9c863910..daddfa51853e 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -69,11 +69,10 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location) spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) { - int i = 1000; iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); ioread32(ioaddr + 0xA0); ioread32(ioaddr + 0xA0); - while (--i > 0) { + for (i = 1000; i >= 0; --i) { barrier(); if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000)) break; @@ -131,13 +130,12 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) { - int i = 1000; iowrite32(cmd, ioaddr + 0xA0); - do { + for (i = 1000; i >= 0; --i) { barrier(); if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000)) break; - } while (--i > 0); + } spin_unlock_irqrestore(&tp->mii_lock, flags); return; } diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 19abbc36b60a..0afa2d4f9472 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -201,8 +201,38 @@ enum desc_status_bits { DescStartPkt = 0x20000000, DescEndRing = 0x02000000, DescUseLink = 0x01000000, - RxDescFatalErr = 0x008000, + + /* + * 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 = 0x00000300, + /* + * 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 }; diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index bee75fa87a9c..2abb5d3becc6 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -255,6 +255,7 @@ const char tulip_media_cap[32] = static void tulip_tx_timeout(struct net_device *dev); static void tulip_init_ring(struct net_device *dev); +static void tulip_free_ring(struct net_device *dev); static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); static int tulip_open(struct net_device *dev); static int tulip_close(struct net_device *dev); @@ -502,16 +503,21 @@ tulip_open(struct net_device *dev) { int retval; - if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) - return retval; - tulip_init_ring (dev); + retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto free_ring; + tulip_up (dev); netif_start_queue (dev); return 0; + +free_ring: + tulip_free_ring (dev); + return retval; } @@ -768,23 +774,11 @@ static void tulip_down (struct net_device *dev) tulip_set_power_state (tp, 0, 1); } - -static int tulip_close (struct net_device *dev) +static void tulip_free_ring (struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->base_addr; int i; - netif_stop_queue (dev); - - tulip_down (dev); - - if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, ioread32 (ioaddr + CSR5)); - - free_irq (dev->irq, dev); - /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = tp->rx_buffers[i].skb; @@ -803,6 +797,7 @@ static int tulip_close (struct net_device *dev) dev_kfree_skb (skb); } } + for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = tp->tx_buffers[i].skb; @@ -814,6 +809,24 @@ static int tulip_close (struct net_device *dev) tp->tx_buffers[i].skb = NULL; tp->tx_buffers[i].mapping = 0; } +} + +static int tulip_close (struct net_device *dev) +{ + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + netif_stop_queue (dev); + + tulip_down (dev); + + if (tulip_debug > 1) + printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, ioread32 (ioaddr + CSR5)); + + free_irq (dev->irq, dev); + + tulip_free_ring (dev); return 0; } diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 030e02e63023..c227db079621 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -200,7 +200,7 @@ enum uli526x_CR6_bits { /* Global variable declaration ----------------------------- */ static int __devinitdata printed_version; -static char version[] __devinitdata = +static const char version[] __devinitconst = KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")\n"; diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index f467bf87817d..c61a01b029af 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -139,9 +139,10 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ /* These identify the driver base version and may not be removed. */ -static char version[] = -KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker <becker@scyld.com>\n" -KERN_INFO " http://www.scyld.com/network/drivers.html\n"; +static const char version[] __initconst = + KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " + DRV_RELDATE " Donald Becker <becker@scyld.com>\n" + KERN_INFO " http://www.scyld.com/network/drivers.html\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver"); |