/* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */ /* Written 1998-2001 by Donald Becker.
Current Maintainer: Kevin Brace <kevinbrace@bracecomputerlab.com>
This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Drivers based on or derived from this code fall under the GPL and must retain the authorship, copyright and license notice. This file is not a complete program and may only be used when the entire operating system is licensed under the GPL.
This driver is designed for the VIA VT86C100A Rhine-I. It also works with the Rhine-II (6102) and Rhine-III (6105/6105L/6105LOM and management NIC 6105M).
The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 Annapolis MD 21403
This driver contains some changes from the original Donald Becker version. He may or may not be interested in bug reports on this code. You can find his versions at: http://www.scyld.com/network/via-rhine.html [link no longer provides useful info -jgarzik]
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DRV_NAME "via-rhine"
#include <linux/types.h>
/* A few user-configurable values.
These may be modified when a driver module is loaded. */ staticint debug = 0; #define RHINE_MSG_DEFAULT \
(0x0000)
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1518 effectively disables this feature. */ #ifdefined(__alpha__) || defined(__arm__) || defined(__hppa__) || \ defined(CONFIG_SPARC) || defined(__ia64__) || \ defined(__sh__) || defined(__mips__) staticint rx_copybreak = 1518; #else staticint rx_copybreak; #endif
/* Work-around for broken BIOSes: they are unable to get the chip back out of
power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */ staticbool avoid_D3;
/* * In case you are looking for 'options[]' or 'full_duplex[]', they * are gone. Use ethtool(8) instead.
*/
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
The Rhine has a 64 element 8390-like hash table. */ staticconstint multicast_filter_limit = 32;
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for compile efficiency. * The compiler will convert <unsigned>'%'<2^N> into a bit mask. * Making the Tx ring too large decreases the effectiveness of channel * bonding and packet priority. * With BQL support, we can increase TX ring safely. * There are no ill effects from too-large receive rings.
*/ #define TX_RING_SIZE 64 #define TX_QUEUE_LEN (TX_RING_SIZE - 6) /* Limit ring entries actually used. */ #define RX_RING_SIZE 64
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2*HZ)
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
MODULE_AUTHOR("Donald Becker ");
MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
MODULE_LICENSE("GPL");
module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param(avoid_D3, bool, 0);
MODULE_PARM_DESC(debug, "VIA Rhine debug message flags");
MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
#define MCAM_SIZE 32 #define VCAM_SIZE 32
/* Theory of Operation
I. Board Compatibility
This driver is designed for the VIA 86c100A Rhine-II PCI Fast Ethernet controller.
II. Board-specific settings
Boards with this chip are functional only in a bus-master PCI slot.
Many operational settings are loaded from the EEPROM to the Config word at offset 0x78. For most of these settings, this driver assumes that they are correct. If this driver is compiled to use PCI memory space operations the EEPROM must be configured to enable memory ops.
III. Driver operation
IIIa. Ring buffers
This driver uses two statically allocated fixed-size descriptor lists formed into rings by a branch from the final descriptor to the beginning of the list. The ring sizes are set at compile time by RX/TX_RING_SIZE.
IIIb/c. Transmit/Receive Structure
This driver attempts to use a zero-copy receive and transmit scheme.
Alas, all data buffers are required to start on a 32 bit boundary, so the driver must often copy transmit packets into bounce buffers.
The driver allocates full frame size skbuffs for the Rx ring buffers at open() time and passes the skb->data field to the chip as receive data buffers. When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is copied to the new skbuff. When the incoming frame is larger, the skbuff is passed directly up the protocol stack. Buffers consumed this way are replaced by newly allocated skbuffs in the last phase of rhine_rx().
The RX_COPYBREAK value is chosen to trade-off the memory wasted by using a full-sized skbuff for small frames vs. the copying costs of larger frames. New boards are typically used in generously configured machines and the underfilled buffers have negligible impact compared to the benefit of a single allocation size, so the default value of zero results in never copying packets. When copying is done, the cost is usually mitigated by using a combined copy/checksum routine. Copying also preloads the cache, which is most useful with small frames.
Since the VIA chips are only able to transfer data to buffers on 32 bit boundaries, the IP header at offset 14 in an ethernet frame isn't longword aligned for further processing. Copying these unaligned buffers has the beneficial effect of 16-byte aligning the IP header.
IIId. Synchronization
The driver runs as two independent, single-threaded flows of control. One is the send-packet routine, which enforces single-threaded use by the netdev_priv(dev)->lock spinlock. The other thread is the interrupt handler, which is single threaded by the hardware and interrupt handling software.
The send packet thread has partial control over the Tx ring. It locks the netdev_priv(dev)->lock whenever it's queuing a Tx packet. If the next slot in the ring is not available it stops the transmit queue by calling netif_stop_queue.
The interrupt handler has exclusive control over the Rx ring and records stats from the Tx ring. After reaping the stats, it marks the Tx queue entry as empty by incrementing the dirty_tx mark. If at least half of the entries in the Rx ring are available the transmit queue is woken up if it was stopped.
The VT86C100A manual is not reliable information. The 3043 chip does not handle unaligned transmit or receive buffers, resulting in significant performance degradation for bounce buffer copies on transmit and unaligned IP headers on receive. The chip does not pad to minimum transmit length.
*/
/* This table drives the PCI probe routines. It's mostly boilerplate in all of the drivers, and will likely be provided by some future kernel. Note the matching code -- the first table entry matchs all 56** cards but second only the 1234 card.
*/
enum rhine_quirks {
rqWOL = 0x0001, /* Wake-On-LAN support */
rqForceReset = 0x0002,
rq6patterns = 0x0040, /* 6 instead of 4 patterns for WOL */
rqStatusWBRace = 0x0080, /* Tx Status Writeback Error possible */
rqRhineI = 0x0100, /* See comment below */
rqIntPHY = 0x0200, /* Integrated PHY */
rqMgmt = 0x0400, /* Management adapter */
rqNeedEnMMIO = 0x0800, /* Whether the core needs to be * switched from PIO mode to MMIO * (only applies to PCI)
*/
}; /* * rqRhineI: VT86C100A (aka Rhine-I) uses different bits to enable * MMIO as well as for the collision counter and the Tx FIFO underflow * indicator. In addition, Tx and Rx buffers need to 4 byte aligned.
*/
/* Beware of PCI posted writes */ #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
/* OpenFirmware identifiers for platform-bus devices * The .data field is currently only used to store quirks
*/ static u32 vt8500_quirks = rqWOL | rqForceReset | rq6patterns; staticconststruct of_device_id rhine_of_tbl[] = {
{ .compatible = "via,vt8500-rhine", .data = &vt8500_quirks },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(of, rhine_of_tbl);
/* Bits in the CamCon (CAMC) register */ enum camcon_bits {
CAMC_CAMEN=0x01,
CAMC_VCAMSL=0x02,
CAMC_CAMWR=0x04,
CAMC_CAMRD=0x08,
};
/* Bits in the PCIBusConfig1 (BCR1) register */ enum bcr1_bits {
BCR1_POT0=0x01,
BCR1_POT1=0x02,
BCR1_POT2=0x04,
BCR1_CTFT0=0x08,
BCR1_CTFT1=0x10,
BCR1_CTSF=0x20,
BCR1_TXQNOBK=0x40, /* for VT6105 */
BCR1_VIDFR=0x80, /* for VT6105 */
BCR1_MED0=0x40, /* for VT6102 */
BCR1_MED1=0x80, /* for VT6102 */
};
/* Registers we check that mmio and reg are the same. */ staticconstint mmio_verify_registers[] = {
RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD,
0
};
/* The addresses of receive-in-place skbuffs. */ struct sk_buff *rx_skbuff[RX_RING_SIZE];
dma_addr_t rx_skbuff_dma[RX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for later free(). */ struct sk_buff *tx_skbuff[TX_RING_SIZE];
dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
/* Frequently used values: keep some adjacent for cache effect. */
u32 quirks; unsignedint cur_rx; unsignedint cur_tx, dirty_tx; unsignedint rx_buf_sz; /* Based on MTU+slack. */ struct rhine_stats rx_stats; struct rhine_stats tx_stats;
u8 wolopts;
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if; void __iomem *base;
};
#define BYTE_REG_BITS_ON(x, p) do { iowrite8((ioread8((p))|(x)), (p)); } while (0) #define WORD_REG_BITS_ON(x, p) do { iowrite16((ioread16((p))|(x)), (p)); } while (0) #define DWORD_REG_BITS_ON(x, p) do { iowrite32((ioread32((p))|(x)), (p)); } while (0)
#define BYTE_REG_BITS_OFF(x, p) do { iowrite8(ioread8((p)) & (~(x)), (p)); } while (0) #define WORD_REG_BITS_OFF(x, p) do { iowrite16(ioread16((p)) & (~(x)), (p)); } while (0) #define DWORD_REG_BITS_OFF(x, p) do { iowrite32(ioread32((p)) & (~(x)), (p)); } while (0)
#define BYTE_REG_BITS_SET(x, m, p) do { iowrite8((ioread8((p)) & (~(m)))|(x), (p)); } while (0) #define WORD_REG_BITS_SET(x, m, p) do { iowrite16((ioread16((p)) & (~(m)))|(x), (p)); } while (0) #define DWORD_REG_BITS_SET(x, m, p) do { iowrite32((ioread32((p)) & (~(m)))|(x), (p)); } while (0)
/* * Get power related registers into sane state. * Notify user about past WOL event.
*/ staticvoid rhine_power_init(struct net_device *dev)
{ struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base;
u16 wolstat;
if (rp->quirks & rqWOL) { /* Make sure chip is in power state D0 */
iowrite8(ioread8(ioaddr + StickyHW) & 0xFC, ioaddr + StickyHW);
staticvoid enable_mmio(long pioaddr, u32 quirks)
{ int n;
if (quirks & rqNeedEnMMIO) { if (quirks & rqRhineI) { /* More recent docs say that this bit is reserved */
n = inb(pioaddr + ConfigA) | 0x20;
outb(n, pioaddr + ConfigA);
} else {
n = inb(pioaddr + ConfigD) | 0x80;
outb(n, pioaddr + ConfigD);
}
}
}
staticinlineint verify_mmio(struct device *hwdev, long pioaddr, void __iomem *ioaddr,
u32 quirks)
{ if (quirks & rqNeedEnMMIO) { int i = 0;
/* Check that selected MMIO registers match the PIO ones */ while (mmio_verify_registers[i]) { int reg = mmio_verify_registers[i++]; unsignedchar a = inb(pioaddr+reg); unsignedchar b = readb(ioaddr+reg);
if (a != b) {
dev_err(hwdev, "MMIO do not match PIO [%02x] (%02x != %02x)\n",
reg, a, b); return -EIO;
}
}
} return 0;
}
outb(0x20, pioaddr + MACRegEEcsr); for (i = 0; i < 1024; i++) { if (!(inb(pioaddr + MACRegEEcsr) & 0x20)) break;
} if (i > 512)
pr_info("%4d cycles used @ %s:%d\n", i, __func__, __LINE__);
/* * Reloading from EEPROM overwrites ConfigA-D, so we must re-enable * MMIO. If reloading EEPROM was done first this could be avoided, but * it is not known if that still works with the "win98-reboot" problem.
*/
enable_mmio(pioaddr, rp->quirks);
/* Turn off EEPROM-controlled wake-up (magic packet) */ if (rp->quirks & rqWOL)
iowrite8(ioread8(ioaddr + ConfigA) & 0xFC, ioaddr + ConfigA);
/* * Clears the "tally counters" for CRC errors and missed frames(?). * It has been reported that some chips need a write of 0 to clear * these, for others the counters are set to 1 when written to and * instead cleared when read. So we clear them both ways ...
*/
iowrite32(0, ioaddr + RxMissed);
ioread16(ioaddr + RxCRCErrs);
ioread16(ioaddr + RxMissed);
}
staticint rhine_init_one_common(struct device *hwdev, u32 quirks, long pioaddr, void __iomem *ioaddr, int irq)
{ struct net_device *dev; struct rhine_private *rp; int i, rc, phy_id;
u8 addr[ETH_ALEN]; constchar *name;
/* this should always be supported */
rc = dma_set_mask(hwdev, DMA_BIT_MASK(32)); if (rc) {
dev_err(hwdev, "32-bit DMA addresses not supported by the card!?\n"); goto err_out;
}
dev = alloc_etherdev(sizeof(struct rhine_private)); if (!dev) {
rc = -ENOMEM; goto err_out;
}
SET_NETDEV_DEV(dev, hwdev);
/* Get chip registers into a sane state */
rhine_power_init(dev);
rhine_hw_init(dev, pioaddr);
for (i = 0; i < 6; i++)
addr[i] = ioread8(ioaddr + StationAddr + i);
eth_hw_addr_set(dev, addr);
if (!is_valid_ether_addr(dev->dev_addr)) { /* Report it and use a random ethernet address instead */
netdev_err(dev, "Invalid MAC address: %pM\n", dev->dev_addr);
eth_hw_addr_random(dev);
netdev_info(dev, "Using random MAC address: %pM\n",
dev->dev_addr);
}
/* For Rhine-I/II, phy_id is loaded from EEPROM */ if (!phy_id)
phy_id = ioread8(ioaddr + 0x6C);
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev); if (rc) goto err_out_free_netdev;
if (rp->quirks & rqRhineI)
name = "Rhine"; elseif (rp->quirks & rqStatusWBRace)
name = "Rhine II"; elseif (rp->quirks & rqMgmt)
name = "Rhine III (Management Adapter)"; else
name = "Rhine III";
/* This driver was written to use PCI memory space. Some early versions * of the Rhine may only work correctly with I/O space accesses. * TODO: determine for which revisions this is true and assign the flag * in code as opposed to this Kconfig option (???)
*/ #ifdef CONFIG_VIA_RHINE_MMIO
u32 quirks = rqNeedEnMMIO; #else
u32 quirks = 0; #endif
rc = pci_enable_device(pdev); if (rc) goto err_out;
/* Init the ring entries */ for (i = 0; i < RX_RING_SIZE; i++) {
rp->rx_ring[i].rx_status = 0;
rp->rx_ring[i].desc_length = cpu_to_le32(rp->rx_buf_sz);
next += sizeof(struct rx_desc);
rp->rx_ring[i].next_desc = cpu_to_le32(next);
rp->rx_skbuff[i] = NULL;
} /* Mark the last entry as wrapping the ring. */
rp->rx_ring[i-1].next_desc = cpu_to_le32(rp->rx_ring_dma);
/* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { struct rhine_skb_dma sd;
/* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) {
rp->rx_ring[i].rx_status = 0;
rp->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ if (rp->rx_skbuff[i]) {
dma_unmap_single(hwdev,
rp->rx_skbuff_dma[i],
rp->rx_buf_sz, DMA_FROM_DEVICE);
dev_kfree_skb(rp->rx_skbuff[i]);
}
rp->rx_skbuff[i] = NULL;
}
}
/* Enable MII link status auto-polling (required for IntrLinkChange) */ staticvoid rhine_enable_linkmon(struct rhine_private *rp)
{ void __iomem *ioaddr = rp->base;
rp->cur_tx++; /* * Nobody wants cur_tx write to rot for ages after the NIC will have * seen the transmit request, especially as the transmit completion * handler could miss it.
*/
smp_wmb();
if (skb_vlan_tag_present(skb)) /* Tx queues are bits 7-0 (first Tx queue: bit 7) */
BYTE_REG_BITS_ON(1 << 7, ioaddr + TQWake);
/* Wake the potentially-idle transmit channel */
iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
ioaddr + ChipCmd1);
IOSYNC;
/* dirty_tx may be pessimistically out-of-sync. See rhine_tx. */ if (rhine_tx_queue_full(rp)) {
netif_stop_queue(dev);
smp_rmb(); /* Rejuvenate. */ if (!rhine_tx_queue_full(rp))
netif_wake_queue(dev);
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
{ struct net_device *dev = dev_instance; struct rhine_private *rp = netdev_priv(dev);
u32 status; int handled = 0;
status = rhine_get_events(rp);
netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status);
/* This routine is logically part of the interrupt handler, but isolated
for clarity. */ staticvoid rhine_tx(struct net_device *dev)
{ struct rhine_private *rp = netdev_priv(dev); struct device *hwdev = dev->dev.parent; unsignedint pkts_compl = 0, bytes_compl = 0; unsignedint dirty_tx = rp->dirty_tx; unsignedint cur_tx; struct sk_buff *skb;
/* * The race with rhine_start_tx does not matter here as long as the * driver enforces a value of cur_tx that was relevant when the * packet was scheduled to the network chipset. * Executive summary: smp_rmb() balances smp_wmb() in rhine_start_tx.
*/
smp_rmb();
cur_tx = rp->cur_tx; /* find and cleanup dirty tx descriptors */ while (dirty_tx != cur_tx) { unsignedint entry = dirty_tx % TX_RING_SIZE;
u32 txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
netif_dbg(rp, tx_done, dev, "Tx scavenge %d status %08x\n",
entry, txstatus); if (txstatus & DescOwn) break;
skb = rp->tx_skbuff[entry]; if (txstatus & 0x8000) {
netif_dbg(rp, tx_done, dev, "Transmit error, Tx status %08x\n", txstatus);
dev->stats.tx_errors++; if (txstatus & 0x0400)
dev->stats.tx_carrier_errors++; if (txstatus & 0x0200)
dev->stats.tx_window_errors++; if (txstatus & 0x0100)
dev->stats.tx_aborted_errors++; if (txstatus & 0x0080)
dev->stats.tx_heartbeat_errors++; if (((rp->quirks & rqRhineI) && txstatus & 0x0002) ||
(txstatus & 0x0800) || (txstatus & 0x1000)) {
dev->stats.tx_fifo_errors++;
rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); break; /* Keep the skb - we try again */
} /* Transmitter restarted in 'abnormal' handler. */
} else { if (rp->quirks & rqRhineI)
dev->stats.collisions += (txstatus >> 3) & 0x0F; else
dev->stats.collisions += txstatus & 0x0F;
netif_dbg(rp, tx_done, dev, "collisions: %1.1x:%1.1x\n",
(txstatus >> 3) & 0xF, txstatus & 0xF);
/* cur_tx may be optimistically out-of-sync. See rhine_start_tx. */ if (!rhine_tx_queue_full(rp) && netif_queue_stopped(dev)) {
netif_wake_queue(dev);
smp_rmb(); /* Rejuvenate. */ if (rhine_tx_queue_full(rp))
netif_stop_queue(dev);
}
}
/** * rhine_get_vlan_tci - extract TCI from Rx data buffer * @skb: pointer to sk_buff * @data_size: used data area of the buffer including CRC * * If hardware VLAN tag extraction is enabled and the chip indicates a 802.1Q * packet, the extracted 802.1Q header (2 bytes TPID + 2 bytes TCI) is 4-byte * aligned following the CRC.
*/ staticinline u16 rhine_get_vlan_tci(struct sk_buff *skb, int data_size)
{
u8 *trailer = (u8 *)skb->data + ((data_size + 3) & ~3) + 2; return be16_to_cpup((__be16 *)trailer);
}
staticinlinevoid rhine_rx_vlan_tag(struct sk_buff *skb, struct rx_desc *desc, int data_size)
{
dma_rmb(); if (unlikely(desc->desc_length & cpu_to_le32(DescTag))) {
u16 vlan_tci;
/* Process up to limit frames from receive ring */ staticint rhine_rx(struct net_device *dev, int limit)
{ struct rhine_private *rp = netdev_priv(dev); struct device *hwdev = dev->dev.parent; int entry = rp->cur_rx % RX_RING_SIZE; int count;
/* If EOP is set on the next entry, it's a new packet. Send it up. */ for (count = 0; count < limit; ++count) { struct rx_desc *desc = rp->rx_ring + entry;
u32 desc_status = le32_to_cpu(desc->rx_status); int data_size = desc_status >> 16;
if (desc_status & DescOwn) break;
netif_dbg(rp, rx_status, dev, "%s() status %08x\n", __func__,
desc_status);
if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { if ((desc_status & RxWholePkt) != RxWholePkt) {
netdev_warn(dev, "Oversized Ethernet frame spanned multiple buffers, " "entry %#x length %d status %08x!\n",
entry, data_size,
desc_status);
dev->stats.rx_length_errors++;
} elseif (desc_status & RxErr) { /* There was a error. */
netif_dbg(rp, rx_err, dev, "%s() Rx error %08x\n", __func__,
desc_status);
dev->stats.rx_errors++; if (desc_status & 0x0030)
dev->stats.rx_length_errors++; if (desc_status & 0x0048)
dev->stats.rx_fifo_errors++; if (desc_status & 0x0004)
dev->stats.rx_frame_errors++; if (desc_status & 0x0002) { /* this can also be updated outside the interrupt handler */
spin_lock(&rp->lock);
dev->stats.rx_crc_errors++;
spin_unlock(&rp->lock);
}
}
} else { /* Length should omit the CRC */ int pkt_len = data_size - 4; 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 = netdev_alloc_skb_ip_align(dev, pkt_len); if (unlikely(!skb)) goto drop;
/* * If new errors occurred, we need to sort them out before doing Tx. * In that case the ISR will be back here RSN anyway.
*/
intr_status = rhine_get_events(rp);
if ((intr_status & IntrTxErrSummary) == 0) {
/* We know better than the chip where it should continue. */
iowrite32(rp->tx_ring_dma + entry * sizeof(struct tx_desc),
ioaddr + TxRingPtr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.