Commit 4df7c015 authored by Jeff Garzik's avatar Jeff Garzik

Hand merge.

parents a925c40f 5c6c0af0
...@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail. ...@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail.
which enables the bus master bit in PCI_COMMAND register and also fixes which enables the bus master bit in PCI_COMMAND register and also fixes
the latency timer value if it's set to something bogus by the BIOS. the latency timer value if it's set to something bogus by the BIOS.
If you want to use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables bit PCI_COMMAND bit for Mem-Wr-Inval
and also ensures that the cache line size register is set correctly.
Make sure to check the return value of pci_set_mwi(), not all architectures
may support Memory-Write-Invalidate.
4. How to access PCI config space 4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...@@ -202,6 +207,8 @@ pci_resource_end() Returns bus end address for a given PCI region ...@@ -202,6 +207,8 @@ pci_resource_end() Returns bus end address for a given PCI region
pci_resource_len() Returns the byte length of a PCI region pci_resource_len() Returns the byte length of a PCI region
pci_set_drvdata() Set private driver data pointer for a pci_dev pci_set_drvdata() Set private driver data pointer for a pci_dev
pci_get_drvdata() Return private driver data pointer for a pci_dev pci_get_drvdata() Return private driver data pointer for a pci_dev
pci_set_mwi() Enable Memory-Write-Invalidate transactions.
pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
7. Miscellaneous hints 7. Miscellaneous hints
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* /*
Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com>
Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c] Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
Copyright 2001 Manfred Spraul [natsemi.c] Copyright 2001 Manfred Spraul [natsemi.c]
Copyright 1999-2001 by Donald Becker. [natsemi.c] Copyright 1999-2001 by Donald Becker. [natsemi.c]
...@@ -29,8 +30,8 @@ ...@@ -29,8 +30,8 @@
* Consider Rx interrupt mitigation using TimerIntr * Consider Rx interrupt mitigation using TimerIntr
* Implement 8139C+ statistics dump; maybe not... * Implement 8139C+ statistics dump; maybe not...
h/w stats can be reset only by software reset h/w stats can be reset only by software reset
* Rx checksumming
* Tx checksumming * Tx checksumming
* Handle netif_rx return value
* ETHTOOL_GREGS, ETHTOOL_[GS]WOL, * ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
* Investigate using skb->priority with h/w VLAN priority * Investigate using skb->priority with h/w VLAN priority
* Investigate using High Priority Tx Queue with skb->priority * Investigate using High Priority Tx Queue with skb->priority
...@@ -38,8 +39,8 @@ ...@@ -38,8 +39,8 @@
* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error * Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
* Implement Tx software interrupt mitigation via * Implement Tx software interrupt mitigation via
Tx descriptor bit Tx descriptor bit
* Determine correct value for CP_{MIN,MAX}_MTU, instead of * The real minimum of CP_MIN_MTU is 4 bytes. However,
using conservative guesses. for this to be supported, one must(?) turn on packet padding.
*/ */
...@@ -48,8 +49,10 @@ ...@@ -48,8 +49,10 @@
#define DRV_RELDATE "Feb 27, 2002" #define DRV_RELDATE "Feb 27, 2002"
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -57,9 +60,15 @@ ...@@ -57,9 +60,15 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/crc32.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define CP_VLAN_TAG_USED 0
#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
do { (tx_desc)->opts2 = 0; } while (0)
/* These identify the driver base version and may not be removed. */ /* These identify the driver base version and may not be removed. */
static char version[] __devinitdata = static char version[] __devinitdata =
KERN_INFO DRV_NAME " 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; KERN_INFO DRV_NAME " 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
...@@ -110,8 +119,8 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered mul ...@@ -110,8 +119,8 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered mul
#define TX_TIMEOUT (6*HZ) #define TX_TIMEOUT (6*HZ)
/* hardware minimum and maximum for a single frame's data payload */ /* hardware minimum and maximum for a single frame's data payload */
#define CP_MIN_MTU 60 /* FIXME: this is a guess */ #define CP_MIN_MTU 60 /* TODO: allow lower, but pad */
#define CP_MAX_MTU 1500 /* FIXME: this is a guess */ #define CP_MAX_MTU 4096
enum { enum {
/* NIC register offsets */ /* NIC register offsets */
...@@ -153,12 +162,17 @@ enum { ...@@ -153,12 +162,17 @@ enum {
IPCS = (1 << 18), /* Calculate IP checksum */ IPCS = (1 << 18), /* Calculate IP checksum */
UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ UDPCS = (1 << 17), /* Calculate UDP/IP checksum */
TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ TCPCS = (1 << 16), /* Calculate TCP/IP checksum */
TxVlanTag = (1 << 17), /* Add VLAN tag */
RxVlanTagged = (1 << 16), /* Rx VLAN tag available */
IPFail = (1 << 15), /* IP checksum failed */ IPFail = (1 << 15), /* IP checksum failed */
UDPFail = (1 << 14), /* UDP/IP checksum failed */ UDPFail = (1 << 14), /* UDP/IP checksum failed */
TCPFail = (1 << 13), /* TCP/IP checksum failed */ TCPFail = (1 << 13), /* TCP/IP checksum failed */
NormalTxPoll = (1 << 6), /* One or more normal Tx packets to send */ NormalTxPoll = (1 << 6), /* One or more normal Tx packets to send */
PID1 = (1 << 17), /* 2 protocol id bits: 0==non-IP, */ PID1 = (1 << 17), /* 2 protocol id bits: 0==non-IP, */
PID0 = (1 << 16), /* 1==UDP/IP, 2==TCP/IP, 3==IP */ PID0 = (1 << 16), /* 1==UDP/IP, 2==TCP/IP, 3==IP */
RxProtoTCP = 2,
RxProtoUDP = 1,
RxProtoIP = 3,
TxFIFOUnder = (1 << 25), /* Tx FIFO underrun */ TxFIFOUnder = (1 << 25), /* Tx FIFO underrun */
TxOWC = (1 << 22), /* Tx Out-of-window collision */ TxOWC = (1 << 22), /* Tx Out-of-window collision */
TxLinkFail = (1 << 21), /* Link failed during Tx of packet */ TxLinkFail = (1 << 21), /* Link failed during Tx of packet */
...@@ -208,6 +222,7 @@ enum { ...@@ -208,6 +222,7 @@ enum {
TxOn = (1 << 2), /* Tx mode enable */ TxOn = (1 << 2), /* Tx mode enable */
/* C+ mode command register */ /* C+ mode command register */
RxVlanOn = (1 << 6), /* Rx VLAN de-tagging enable */
RxChkSum = (1 << 5), /* Rx checksum offload enable */ RxChkSum = (1 << 5), /* Rx checksum offload enable */
PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */ PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */
CpRxOn = (1 << 1), /* Rx mode enable */ CpRxOn = (1 << 1), /* Rx mode enable */
...@@ -278,6 +293,10 @@ struct cp_private { ...@@ -278,6 +293,10 @@ struct cp_private {
unsigned rx_buf_sz; unsigned rx_buf_sz;
dma_addr_t ring_dma; dma_addr_t ring_dma;
#if CP_VLAN_TAG_USED
struct vlan_group *vlgrp;
#endif
u32 msg_enable; u32 msg_enable;
struct net_device_stats net_stats; struct net_device_stats net_stats;
...@@ -335,14 +354,21 @@ static inline void cp_set_rxbufsize (struct cp_private *cp) ...@@ -335,14 +354,21 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
cp->rx_buf_sz = PKT_BUF_SZ; cp->rx_buf_sz = PKT_BUF_SZ;
} }
static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb) static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
struct cp_desc *desc)
{ {
skb->protocol = eth_type_trans (skb, cp->dev); skb->protocol = eth_type_trans (skb, cp->dev);
cp->net_stats.rx_packets++; cp->net_stats.rx_packets++;
cp->net_stats.rx_bytes += skb->len; cp->net_stats.rx_bytes += skb->len;
cp->dev->last_rx = jiffies; cp->dev->last_rx = jiffies;
netif_rx (skb);
#if CP_VLAN_TAG_USED
if (cp->vlgrp && (desc->opts2 & RxVlanTagged)) {
vlan_hwaccel_rx(skb, cp->vlgrp, desc->opts2 & 0xffff);
} else
#endif
netif_rx(skb);
} }
static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
...@@ -425,13 +451,26 @@ static void cp_rx_frag (struct cp_private *cp, unsigned rx_tail, ...@@ -425,13 +451,26 @@ static void cp_rx_frag (struct cp_private *cp, unsigned rx_tail,
cp_rx_err_acct(cp, rx_tail, status, len); cp_rx_err_acct(cp, rx_tail, status, len);
dev_kfree_skb_irq(copy_skb); dev_kfree_skb_irq(copy_skb);
} else } else
cp_rx_skb(cp, copy_skb); cp_rx_skb(cp, copy_skb, &cp->rx_ring[rx_tail]);
cp->frag_skb = NULL; cp->frag_skb = NULL;
} else { } else {
cp->frag_skb = copy_skb; cp->frag_skb = copy_skb;
} }
} }
static inline unsigned int cp_rx_csum_ok (u32 status)
{
unsigned int protocol = (status >> 16) & 0x3;
if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
return 1;
else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
return 1;
else if ((protocol == RxProtoIP) && (!(status & IPFail)))
return 1;
return 0;
}
static void cp_rx (struct cp_private *cp) static void cp_rx (struct cp_private *cp)
{ {
unsigned rx_tail = cp->rx_tail; unsigned rx_tail = cp->rx_tail;
...@@ -441,13 +480,15 @@ static void cp_rx (struct cp_private *cp) ...@@ -441,13 +480,15 @@ static void cp_rx (struct cp_private *cp)
u32 status, len; u32 status, len;
dma_addr_t mapping; dma_addr_t mapping;
struct sk_buff *skb, *new_skb; struct sk_buff *skb, *new_skb;
struct cp_desc *desc;
unsigned buflen; unsigned buflen;
skb = cp->rx_skb[rx_tail].skb; skb = cp->rx_skb[rx_tail].skb;
if (!skb) if (!skb)
BUG(); BUG();
rmb();
status = le32_to_cpu(cp->rx_ring[rx_tail].opts1); desc = &cp->rx_ring[rx_tail];
status = le32_to_cpu(desc->opts1);
if (status & DescOwn) if (status & DescOwn)
break; break;
...@@ -480,7 +521,13 @@ static void cp_rx (struct cp_private *cp) ...@@ -480,7 +521,13 @@ static void cp_rx (struct cp_private *cp)
pci_unmap_single(cp->pdev, mapping, pci_unmap_single(cp->pdev, mapping,
buflen, PCI_DMA_FROMDEVICE); buflen, PCI_DMA_FROMDEVICE);
/* Handle checksum offloading for incoming packets. */
if (cp_rx_csum_ok(status))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, len); skb_put(skb, len);
mapping = mapping =
...@@ -489,15 +536,14 @@ static void cp_rx (struct cp_private *cp) ...@@ -489,15 +536,14 @@ static void cp_rx (struct cp_private *cp)
buflen, PCI_DMA_FROMDEVICE); buflen, PCI_DMA_FROMDEVICE);
cp->rx_skb[rx_tail].skb = new_skb; cp->rx_skb[rx_tail].skb = new_skb;
cp_rx_skb(cp, skb); cp_rx_skb(cp, skb, desc);
rx_next: rx_next:
if (rx_tail == (CP_RX_RING_SIZE - 1)) if (rx_tail == (CP_RX_RING_SIZE - 1))
cp->rx_ring[rx_tail].opts1 = desc->opts1 = cpu_to_le32(DescOwn | RingEnd |
cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz); cp->rx_buf_sz);
else else
cp->rx_ring[rx_tail].opts1 = desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
cpu_to_le32(DescOwn | cp->rx_buf_sz);
cp->rx_ring[rx_tail].opts2 = 0; cp->rx_ring[rx_tail].opts2 = 0;
cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping); cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping);
rx_tail = NEXT_RX(rx_tail); rx_tail = NEXT_RX(rx_tail);
...@@ -606,6 +652,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -606,6 +652,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
struct cp_private *cp = dev->priv; struct cp_private *cp = dev->priv;
unsigned entry; unsigned entry;
u32 eor; u32 eor;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
spin_lock_irq(&cp->lock); spin_lock_irq(&cp->lock);
...@@ -615,6 +664,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -615,6 +664,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
return 1; return 1;
} }
#if CP_VLAN_TAG_USED
if (cp->vlgrp && vlan_tx_tag_present(skb))
vlan_tag = TxVlanTag | vlan_tx_tag_get(skb);
#endif
entry = cp->tx_head; entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (skb_shinfo(skb)->nr_frags == 0) { if (skb_shinfo(skb)->nr_frags == 0) {
...@@ -624,7 +678,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -624,7 +678,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
len = skb->len; len = skb->len;
mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE); mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
txd->opts2 = 0; CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping); txd->addr_lo = cpu_to_le32(mapping);
wmb(); wmb();
...@@ -677,7 +731,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -677,7 +731,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
ctrl |= LastFrag; ctrl |= LastFrag;
txd = &cp->tx_ring[entry]; txd = &cp->tx_ring[entry];
txd->opts2 = 0; CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping); txd->addr_lo = cpu_to_le32(mapping);
wmb(); wmb();
...@@ -691,7 +745,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -691,7 +745,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
} }
txd = &cp->tx_ring[first_entry]; txd = &cp->tx_ring[first_entry];
txd->opts2 = 0; CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(first_mapping); txd->addr_lo = cpu_to_le32(first_mapping);
wmb(); wmb();
...@@ -826,7 +880,7 @@ static void cp_reset_hw (struct cp_private *cp) ...@@ -826,7 +880,7 @@ static void cp_reset_hw (struct cp_private *cp)
static inline void cp_start_hw (struct cp_private *cp) static inline void cp_start_hw (struct cp_private *cp)
{ {
cpw8(Cmd, RxOn | TxOn); cpw8(Cmd, RxOn | TxOn);
cpw16(CpCmd, PCIMulRW | CpRxOn | CpTxOn); cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
} }
static void cp_init_hw (struct cp_private *cp) static void cp_init_hw (struct cp_private *cp)
...@@ -1171,7 +1225,30 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1171,7 +1225,30 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
return rc; return rc;
} }
#if CP_VLAN_TAG_USED
static int cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct cp_private *cp = dev->priv;
spin_lock_irq(&cp->lock);
cp->vlgrp = grp;
cpw16(CpCmd, cpr16(CpCmd) | RxVlanOn);
spin_unlock_irq(&cp->lock);
return 0;
}
static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct cp_private *cp = dev->priv;
spin_lock_irq(&cp->lock);
cpw16(CpCmd, cpr16(CpCmd) & ~RxVlanOn);
if (cp->vlgrp)
cp->vlgrp->vlan_devices[vid] = NULL;
spin_unlock_irq(&cp->lock);
}
#endif
/* Serial EEPROM section. */ /* Serial EEPROM section. */
...@@ -1337,6 +1414,11 @@ static int __devinit cp_init_one (struct pci_dev *pdev, ...@@ -1337,6 +1414,11 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
#ifdef CP_TX_CHECKSUM #ifdef CP_TX_CHECKSUM
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
#endif #endif
#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = cp_vlan_rx_register;
dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
#endif
dev->irq = pdev->irq; dev->irq = pdev->irq;
......
...@@ -148,7 +148,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then ...@@ -148,7 +148,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi fi
if [ "$CONFIG_NET_PCI" = "y" ]; then if [ "$CONFIG_NET_PCI" = "y" ]; then
dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI
dep_tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Adaptec Starfire/DuraLAN support' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI
if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then
dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL
fi fi
......
...@@ -128,7 +128,7 @@ static char *e1000_strings[] = { ...@@ -128,7 +128,7 @@ static char *e1000_strings[] = {
"IBM Mobile, Desktop & Server Adapters" "IBM Mobile, Desktop & Server Adapters"
}; };
/* Local Function Prototypes */ /* e1000_main.c Function Prototypes */
int e1000_up(struct e1000_adapter *adapter); int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter);
...@@ -193,23 +193,6 @@ MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); ...@@ -193,23 +193,6 @@ MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
#ifdef EXPORT_SYMTAB
EXPORT_SYMBOL(e1000_init_module);
EXPORT_SYMBOL(e1000_exit_module);
EXPORT_SYMBOL(e1000_probe);
EXPORT_SYMBOL(e1000_remove);
EXPORT_SYMBOL(e1000_open);
EXPORT_SYMBOL(e1000_close);
EXPORT_SYMBOL(e1000_xmit_frame);
EXPORT_SYMBOL(e1000_intr);
EXPORT_SYMBOL(e1000_set_multi);
EXPORT_SYMBOL(e1000_change_mtu);
EXPORT_SYMBOL(e1000_set_mac);
EXPORT_SYMBOL(e1000_get_stats);
EXPORT_SYMBOL(e1000_watchdog);
EXPORT_SYMBOL(e1000_ioctl);
#endif
/** /**
* e1000_init_module - Driver Registration Routine * e1000_init_module - Driver Registration Routine
* *
......
...@@ -96,13 +96,18 @@ ...@@ -96,13 +96,18 @@
LK1.3.5 (jgarzik) LK1.3.5 (jgarzik)
- ethtool NWAY_RST, GLINK, [GS]MSGLVL support - ethtool NWAY_RST, GLINK, [GS]MSGLVL support
LK1.3.6 (Ion Badulescu)
- Sparc64 support and fixes
- Better stats and error handling
TODO: TODO:
- implement tx_timeout() properly - implement tx_timeout() properly
- VLAN support
*/ */
#define DRV_NAME "starfire" #define DRV_NAME "starfire"
#define DRV_VERSION "1.03+LK1.3.5" #define DRV_VERSION "1.03+LK1.3.6"
#define DRV_RELDATE "November 17, 2001" #define DRV_RELDATE "March 6, 2002"
#include <linux/version.h> #include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -128,8 +133,11 @@ ...@@ -128,8 +133,11 @@
* for this driver to really use the firmware. Note that Rx/Tx * for this driver to really use the firmware. Note that Rx/Tx
* hardware TCP checksumming is not possible without the firmware. * hardware TCP checksumming is not possible without the firmware.
* *
* I'm currently [Feb 2001] talking to Adaptec about this redistribution * If Adaptec could allow redistribution of the firmware (even in binary
* issue. Stay tuned... * format), life would become a lot easier. Unfortunately, I've lost my
* Adaptec contacts, so progress on this front is rather unlikely to
* occur. If anybody from Adaptec reads this and can help with this matter,
* please let me know...
*/ */
#undef HAS_FIRMWARE #undef HAS_FIRMWARE
/* /*
...@@ -609,6 +617,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, ...@@ -609,6 +617,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
long ioaddr; long ioaddr;
int drv_flags, io_size; int drv_flags, io_size;
int boguscnt; int boguscnt;
u16 cmd;
u8 cache; u8 cache;
/* when built into the kernel, we only print version if device is found */ /* when built into the kernel, we only print version if device is found */
...@@ -644,14 +653,22 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, ...@@ -644,14 +653,22 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
goto err_out_free_netdev; goto err_out_free_netdev;
} }
ioaddr = (long) ioremap (ioaddr, io_size); /* ioremap is borken in Linux-2.2.x/sparc64 */
#if !defined(CONFIG_SPARC64) || LINUX_VERSION_CODE > 0x20300
ioaddr = (long) ioremap(ioaddr, io_size);
if (!ioaddr) { if (!ioaddr) {
printk (KERN_ERR DRV_NAME " %d: cannot remap 0x%x @ 0x%lx, aborting\n", printk (KERN_ERR DRV_NAME " %d: cannot remap 0x%x @ 0x%lx, aborting\n",
card_idx, io_size, ioaddr); card_idx, io_size, ioaddr);
goto err_out_free_res; goto err_out_free_res;
} }
#endif /* !CONFIG_SPARC64 || Linux 2.3.0+ */
pci_set_master(pdev);
pci_set_master (pdev); /* enable MWI -- it vastly improves Rx performance on sparc64 */
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_INVALIDATE;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
/* set PCI cache size */ /* set PCI cache size */
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache);
...@@ -670,7 +687,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, ...@@ -670,7 +687,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* Serial EEPROM reads are hidden by the hardware. */ /* Serial EEPROM reads are hidden by the hardware. */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i); dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20 - i);
#if ! defined(final_version) /* Dump the EEPROM contents during development. */ #if ! defined(final_version) /* Dump the EEPROM contents during development. */
if (debug > 4) if (debug > 4)
...@@ -932,7 +949,7 @@ static int netdev_open(struct net_device *dev) ...@@ -932,7 +949,7 @@ static int netdev_open(struct net_device *dev)
/* Fill both the unused Tx SA register and the Rx perfect filter. */ /* Fill both the unused Tx SA register and the Rx perfect filter. */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
writeb(dev->dev_addr[i], ioaddr + StationAddr + 5-i); writeb(dev->dev_addr[i], ioaddr + StationAddr + 5 - i);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
u16 *eaddrs = (u16 *)dev->dev_addr; u16 *eaddrs = (u16 *)dev->dev_addr;
long setup_frm = ioaddr + PerfFilterTable + i * 16; long setup_frm = ioaddr + PerfFilterTable + i * 16;
...@@ -979,9 +996,9 @@ static int netdev_open(struct net_device *dev) ...@@ -979,9 +996,9 @@ static int netdev_open(struct net_device *dev)
#ifdef HAS_FIRMWARE #ifdef HAS_FIRMWARE
/* Load Rx/Tx firmware into the frame processors */ /* Load Rx/Tx firmware into the frame processors */
for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4); writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4); writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
writel(0x003F, ioaddr + GenCtrl); writel(0x003F, ioaddr + GenCtrl);
#else /* not HAS_FIRMWARE */ #else /* not HAS_FIRMWARE */
...@@ -1156,8 +1173,8 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1156,8 +1173,8 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping); np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping);
#ifdef ZEROCOPY #ifdef ZEROCOPY
np->tx_ring[entry].first_len = cpu_to_le32(skb_first_frag_len(skb)); np->tx_ring[entry].first_len = cpu_to_le16(skb_first_frag_len(skb));
np->tx_ring[entry].total_len = cpu_to_le32(skb->len); np->tx_ring[entry].total_len = cpu_to_le16(skb->len);
/* Add "| TxDescIntr" to generate Tx-done interrupts. */ /* Add "| TxDescIntr" to generate Tx-done interrupts. */
np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn); np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn);
np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1); np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1);
...@@ -1170,8 +1187,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1170,8 +1187,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr); np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
#ifdef ZEROCOPY #ifdef ZEROCOPY
if (skb->ip_summed == CHECKSUM_HW) if (skb->ip_summed == CHECKSUM_HW) {
np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP); np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP);
np->stats.tx_compressed++;
}
#endif /* ZEROCOPY */ #endif /* ZEROCOPY */
if (debug > 5) { if (debug > 5) {
...@@ -1449,6 +1468,7 @@ static int netdev_rx(struct net_device *dev) ...@@ -1449,6 +1468,7 @@ static int netdev_rx(struct net_device *dev)
#if defined(full_rx_status) || defined(csum_rx_status) #if defined(full_rx_status) || defined(csum_rx_status)
if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) { if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
np->stats.rx_compressed++;
} }
/* /*
* This feature doesn't seem to be working, at least * This feature doesn't seem to be working, at least
...@@ -1580,12 +1600,17 @@ static void netdev_error(struct net_device *dev, int intr_status) ...@@ -1580,12 +1600,17 @@ static void netdev_error(struct net_device *dev, int intr_status)
printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n", printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n",
dev->name, np->tx_threshold * 16); dev->name, np->tx_threshold * 16);
} }
if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrPCIPad)) && debug) if (intr_status & IntrRxGFPDead) {
np->stats.rx_fifo_errors++;
np->stats.rx_errors++;
}
if (intr_status & (IntrNoTxCsum | IntrDMAErr)) {
np->stats.tx_fifo_errors++;
np->stats.tx_errors++;
}
if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrRxGFPDead | IntrNoTxCsum | IntrPCIPad)) && debug)
printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
dev->name, intr_status); dev->name, intr_status);
/* Hmmmmm, it's not clear how to recover from DMA faults. */
if (intr_status & IntrDMAErr)
np->stats.tx_fifo_errors++;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/kmod.h> /* for hotplug_path */ #include <linux/kmod.h> /* for hotplug_path */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cache.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */ #include <asm/dma.h> /* isa_dma_bridge_buggy */
...@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev) ...@@ -848,6 +849,100 @@ pci_set_master(struct pci_dev *dev)
pcibios_set_master(dev); pcibios_set_master(dev);
} }
/**
* pdev_set_mwi - arch helper function for pcibios_set_mwi
* @dev: the PCI device for which MWI is enabled
*
* Helper function for implementation the arch-specific pcibios_set_mwi
* function. Originally copied from drivers/net/acenic.c.
* Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>.
*
* RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
*/
int
pdev_set_mwi(struct pci_dev *dev)
{
int rc = 0;
u8 cache_size;
/*
* Looks like this is necessary to deal with on all architectures,
* even this %$#%$# N440BX Intel based thing doesn't get it right.
* Ie. having two NICs in the machine, one will have the cache
* line set at boot time, the other will not.
*/
pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cache_size);
cache_size <<= 2;
if (cache_size != SMP_CACHE_BYTES) {
printk(KERN_WARNING "PCI: %s PCI cache line size set incorrectly "
"(%i bytes) by BIOS/FW, ",
dev->slot_name, cache_size);
if (cache_size > SMP_CACHE_BYTES) {
printk("expecting %i\n", SMP_CACHE_BYTES);
rc = -EINVAL;
} else {
printk("correcting to %i\n", SMP_CACHE_BYTES);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
SMP_CACHE_BYTES >> 2);
}
}
return rc;
}
/**
* pci_set_mwi - enables memory-write-validate PCI transaction
* @dev: the PCI device for which MWI is enabled
*
* Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
* and then calls @pcibios_set_mwi to do the needed arch specific
* operations or a generic mwi-prep function.
*
* RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
*/
int
pci_set_mwi(struct pci_dev *dev)
{
int rc;
u16 cmd;
#ifdef HAVE_ARCH_PCI_MWI
rc = pcibios_set_mwi(dev);
#else
rc = pdev_set_mwi(dev);
#endif
if (rc)
return rc;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_INVALIDATE)) {
DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name);
cmd |= PCI_COMMAND_INVALIDATE;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/**
* pci_clear_mwi - disables Memory-Write-Invalidate for device dev
* @dev: the PCI device to disable
*
* Disables PCI Memory-Write-Invalidate transaction on the device
*/
void
pci_clear_mwi(struct pci_dev *dev)
{
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (cmd & PCI_COMMAND_INVALIDATE) {
cmd &= ~PCI_COMMAND_INVALIDATE;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
int int
pci_set_dma_mask(struct pci_dev *dev, u64 mask) pci_set_dma_mask(struct pci_dev *dev, u64 mask)
{ {
...@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device); ...@@ -2002,6 +2097,9 @@ EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_find_slot);
EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_find_subsys);
EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
EXPORT_SYMBOL(pdev_set_mwi);
EXPORT_SYMBOL(pci_set_dma_mask); EXPORT_SYMBOL(pci_set_dma_mask);
EXPORT_SYMBOL(pci_dac_set_dma_mask); EXPORT_SYMBOL(pci_dac_set_dma_mask);
EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_assign_resource);
......
...@@ -286,7 +286,7 @@ ctc_tty_tint(ctc_tty_info * info) ...@@ -286,7 +286,7 @@ ctc_tty_tint(ctc_tty_info * info)
if (!info->netdev) { if (!info->netdev) {
if (skb) if (skb)
kfree(skb); kfree_skb(skb);
return 0; return 0;
} }
if (info->flags & CTC_ASYNC_TX_LINESTAT) { if (info->flags & CTC_ASYNC_TX_LINESTAT) {
......
...@@ -564,6 +564,10 @@ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val); ...@@ -564,6 +564,10 @@ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
int pci_enable_device(struct pci_dev *dev); int pci_enable_device(struct pci_dev *dev);
void pci_disable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev);
void pci_set_master(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev);
#define HAVE_PCI_SET_MWI
int pci_set_mwi(struct pci_dev *dev);
void pci_clear_mwi(struct pci_dev *dev);
int pdev_set_mwi(struct pci_dev *dev);
int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_assign_resource(struct pci_dev *dev, int i); int pci_assign_resource(struct pci_dev *dev, int i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment