Commit c1bc73b5 authored by Jeff Garzik's avatar Jeff Garzik

Merge mandrakesoft.com:/home/jgarzik/vanilla/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents 362dff46 4c978e6f
D-Link DL2000-based Gigabit Ethernet Adapter Installation
for Linux
Jan 29, 2002
May 23, 2002
Contents
========
......@@ -202,7 +202,7 @@ media=media_type - Specifies the media type the NIC operates at.
1000mbps_fd and 1000mbps_hd types are only
available for fiber adapter.
vlan=[0|1] - Specifies the VLAN ID. If vlan=0, the
vlan=n - Specifies the VLAN ID. If vlan=0, the
Virtual Local Area Network (VLAN) function is
disable.
......@@ -211,24 +211,34 @@ jumbo=[0|1] - Specifies the jumbo frame support. If jumbo=1,
function is disabled.
Jumbo frame usually improve the performance
int gigabit.
This feature need jumbo frame compatible
remote.
rx_coalesce=n - Rx frame count each interrupt.
rx_timeout=n - Rx DMA wait time for an interrupt. Proper
values of rx_coalesce and rx_timeout bring
a conspicuous performance in the fast machine.
Ex. rx_coalesce=5 and rx_timeout=750
tx_coalesce=n - Tx transmit count each TxComp interrupt.
Setting value larger than 1 will improve
performance, but this is possible to lower
stability in slow UP machines. By default,
tx_coalesce=1. (dl2k)
rx_coalesce=m - Number of rx frame handled each interrupt.
rx_timeout=n - Rx DMA wait time for an interrupt.
If set rx_coalesce > 0, hardware only assert
an interrupt for m frames. Hardware won't
assert rx interrupt until m frames received or
reach timeout of n * 640 nano seconds.
Set proper rx_coalesce and rx_timeout can
reduce congestion collapse and overload which
has been a bottlenect for high speed network.
tx_flow=[1|0] - Specifies the Tx flow control. If tx_flow=1,
the Tx flow control enable.
For example, rx_coalesce=10 rx_timeout=800.
that is, hardware assert only 1 interrupt
for 10 frames received or timeout of 512 us.
tx_coalesce=n - Number of tx frame handled each interrupt.
Set n > 1 can reduce the interrupts
congestion usually lower performance of
high speed network card. Default is 16.
rx_flow=[1|0] - Specifies the Rx flow control. If rx_flow=1,
the Rx flow control enable.
tx_flow=[1|0] - Specifies the Tx flow control. If tx_flow=0,
the Tx flow control disable else driver
autodetect.
rx_flow=[1|0] - Specifies the Rx flow control. If rx_flow=0,
the Rx flow control enable else driver
autodetect.
Configuration Script Sample
......
......@@ -100,13 +100,16 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered mul
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
#define CP_NUM_STATS 14 /* struct cp_dma_stats, plus one */
#define CP_STATS_SIZE 64 /* size in bytes of DMA stats block */
#define CP_REGS_SIZE (0xff + 1)
#define CP_REGS_VER 1 /* version 1 */
#define CP_RX_RING_SIZE 64
#define CP_TX_RING_SIZE 64
#define CP_RING_BYTES \
((sizeof(struct cp_desc) * CP_RX_RING_SIZE) + \
(sizeof(struct cp_desc) * CP_TX_RING_SIZE))
(sizeof(struct cp_desc) * CP_TX_RING_SIZE) + \
CP_STATS_SIZE)
#define NEXT_TX(N) (((N) + 1) & (CP_TX_RING_SIZE - 1))
#define NEXT_RX(N) (((N) + 1) & (CP_RX_RING_SIZE - 1))
#define TX_BUFFS_AVAIL(CP) \
......@@ -135,6 +138,7 @@ enum {
/* NIC register offsets */
MAC0 = 0x00, /* Ethernet hardware address. */
MAR0 = 0x08, /* Multicast filter. */
StatsAddr = 0x10, /* 64-bit start addr of 64-byte DMA stats blk */
TxRingAddr = 0x20, /* 64-bit start addr of Tx ring */
HiTxRingAddr = 0x28, /* 64-bit start addr of high priority Tx ring */
Cmd = 0x37, /* Command register */
......@@ -197,6 +201,9 @@ enum {
RxErrLong = (1 << 21), /* Rx error, packet > 4096 bytes */
RxErrFIFO = (1 << 22), /* Rx error, FIFO overflowed, pkt bad */
/* StatsAddr register */
DumpStats = (1 << 3), /* Begin stats dump */
/* RxConfig register */
RxCfgFIFOShift = 13, /* Shift, to get Rx FIFO thresh value */
RxCfgDMAShift = 8, /* Shift, to get Rx Max DMA value */
......@@ -284,6 +291,22 @@ struct ring_info {
unsigned frag;
};
struct cp_dma_stats {
u64 tx_ok;
u64 rx_ok;
u64 tx_err;
u32 rx_err;
u16 rx_fifo;
u16 frame_align;
u32 tx_ok_1col;
u32 tx_ok_mcol;
u64 rx_ok_phys;
u64 rx_ok_bcast;
u32 rx_ok_mcast;
u16 tx_abort;
u16 tx_underrun;
} __attribute__((packed));
struct cp_extra_stats {
unsigned long rx_frags;
};
......@@ -312,6 +335,8 @@ struct cp_private {
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
struct cp_dma_stats *nic_stats;
dma_addr_t nic_stats_dma;
struct pci_dev *pdev;
u32 rx_config;
......@@ -373,6 +398,26 @@ static struct pci_device_id cp_pci_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
static struct {
const char str[ETH_GSTRING_LEN];
} ethtool_stats_keys[] = {
{ "tx_ok" },
{ "rx_ok" },
{ "tx_err" },
{ "rx_err" },
{ "rx_fifo" },
{ "frame_align" },
{ "tx_ok_1col" },
{ "tx_ok_mcol" },
{ "rx_ok_phys" },
{ "rx_ok_bcast" },
{ "rx_ok_mcast" },
{ "tx_abort" },
{ "tx_underrun" },
{ "rx_frags" },
};
static inline void cp_set_rxbufsize (struct cp_private *cp)
{
unsigned int mtu = cp->dev->mtu;
......@@ -949,9 +994,9 @@ static void cp_init_hw (struct cp_private *cp)
cpw32_f(HiTxRingAddr + 4, 0);
cpw32_f(RxRingAddr, cp->ring_dma);
cpw32_f(RxRingAddr + 4, 0);
cpw32_f(RxRingAddr + 4, 0); /* FIXME: 64-bit PCI */
cpw32_f(TxRingAddr, cp->ring_dma + (sizeof(struct cp_desc) * CP_RX_RING_SIZE));
cpw32_f(TxRingAddr + 4, 0);
cpw32_f(TxRingAddr + 4, 0); /* FIXME: 64-bit PCI */
cpw16(MultiIntr, 0);
......@@ -1010,10 +1055,19 @@ static int cp_init_rings (struct cp_private *cp)
static int cp_alloc_rings (struct cp_private *cp)
{
cp->rx_ring = pci_alloc_consistent(cp->pdev, CP_RING_BYTES, &cp->ring_dma);
if (!cp->rx_ring)
void *mem;
mem = pci_alloc_consistent(cp->pdev, CP_RING_BYTES, &cp->ring_dma);
if (!mem)
return -ENOMEM;
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
mem += (CP_RING_BYTES - CP_STATS_SIZE);
cp->nic_stats = mem;
cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
return cp_init_rings(cp);
}
......@@ -1052,6 +1106,7 @@ static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
cp->nic_stats = NULL;
}
static int cp_open (struct net_device *dev)
......@@ -1181,6 +1236,7 @@ static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
strcpy (info.version, DRV_VERSION);
strcpy (info.bus_info, cp->pdev->slot_name);
info.regdump_len = CP_REGS_SIZE;
info.n_stats = CP_NUM_STATS;
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
......@@ -1359,6 +1415,83 @@ static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
return 0;
}
/* get string list(s) */
case ETHTOOL_GSTRINGS: {
struct ethtool_gstrings estr = { ETHTOOL_GSTRINGS };
if (copy_from_user(&estr, useraddr, sizeof(estr)))
return -EFAULT;
if (estr.string_set != ETH_SS_STATS)
return -EINVAL;
estr.len = CP_NUM_STATS;
if (copy_to_user(useraddr, &estr, sizeof(estr)))
return -EFAULT;
if (copy_to_user(useraddr + sizeof(estr),
&ethtool_stats_keys,
sizeof(ethtool_stats_keys)))
return -EFAULT;
return 0;
}
/* get NIC-specific statistics */
case ETHTOOL_GSTATS: {
struct ethtool_stats estats = { ETHTOOL_GSTATS };
u64 *tmp_stats;
unsigned int work = 100;
const unsigned int sz = sizeof(u64) * CP_NUM_STATS;
int i;
/* begin NIC statistics dump */
cpw32(StatsAddr + 4, 0); /* FIXME: 64-bit PCI */
cpw32(StatsAddr, cp->nic_stats_dma | DumpStats);
cpr32(StatsAddr);
estats.n_stats = CP_NUM_STATS;
if (copy_to_user(useraddr, &estats, sizeof(estats)))
return -EFAULT;
while (work-- > 0) {
if ((cpr32(StatsAddr) & DumpStats) == 0)
break;
cpu_relax();
}
if (cpr32(StatsAddr) & DumpStats)
return -EIO;
tmp_stats = kmalloc(sz, GFP_KERNEL);
if (!tmp_stats)
return -ENOMEM;
memset(tmp_stats, 0, sz);
i = 0;
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
if (i != CP_NUM_STATS)
BUG();
i = copy_to_user(useraddr + sizeof(estats),
tmp_stats, sz);
kfree(tmp_stats);
if (i)
return -EFAULT;
return 0;
}
default:
break;
}
......
/* D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
/*
Copyright (c) 2001,2002 by D-Link Corporation
Copyright (c) 2001, 2002 by D-Link Corporation
Written by Edward Peng.<edward_peng@dlink.com.tw>
Created 03-May-2001, base on Linux' sundance.c.
......@@ -33,12 +33,13 @@
1.11 2002/05/23 Added ISR schedule scheme.
Fixed miscount of rx frame error for DGE-550SX.
Fixed VLAN bug.
1.12 2002/06/13 Lock tx_coalesce=1 on 10/100Mbps mode.
*/
#include "dl2k.h"
static char version[] __devinitdata =
KERN_INFO "D-Link DL2000-based linux driver v1.11 2002/05/23\n";
KERN_INFO "D-Link DL2000-based linux driver v1.12 2002/06/13\n";
#define MAX_UNITS 8
static int mtu[MAX_UNITS];
......@@ -138,15 +139,15 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_MODULE_OWNER (dev);
#ifdef USE_IO_OPS
ioaddr = pci_resource_start (pdev, 0);
#else
#ifdef MEM_MAPPING
ioaddr = pci_resource_start (pdev, 1);
ioaddr = (long) ioremap (ioaddr, RIO_IO_SIZE);
if (!ioaddr) {
err = -ENOMEM;
goto err_out_dev;
}
#else
ioaddr = pci_resource_start (pdev, 0);
#endif
dev->base_addr = ioaddr;
dev->irq = irq;
......@@ -158,6 +159,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
/* Parse manual configuration */
np->an_enable = 1;
np->tx_coalesce = 1;
if (card_idx < MAX_UNITS) {
if (media[card_idx] != NULL) {
np->an_enable = 0;
......@@ -213,7 +215,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
if (tx_coalesce < 1)
tx_coalesce = 1;
if (tx_coalesce > TX_RING_SIZE-1)
else if (tx_coalesce > TX_RING_SIZE-1)
tx_coalesce = TX_RING_SIZE - 1;
}
dev->open = &rio_open;
......@@ -303,7 +305,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_unmap_tx:
pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
err_out_iounmap:
#ifndef USE_IO_OPS
#ifdef MEM_MAPPING
iounmap ((void *) ioaddr);
err_out_dev:
......@@ -361,7 +363,7 @@ parse_eeprom (struct net_device *dev)
}
/* Check CRC */
crc = ~ether_crc_le(256 - 4, sromdata);
crc = ~ether_crc_le (256 - 4, sromdata);
if (psrom->crc != crc) {
printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
return -1;
......@@ -636,7 +638,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
/* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode
* Work around: Always use 1 descriptor in 10Mbps mode */
if (entry % tx_coalesce == 0 || np->speed == 10)
if (entry % np->tx_coalesce == 0 || np->speed == 10)
txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
WordAlignDisable |
TxDMAIndicate |
......@@ -936,6 +938,10 @@ rio_error (struct net_device *dev, int int_status)
mii_get_media_pcs (dev);
else
mii_get_media (dev);
if (np->speed == 1000)
np->tx_coalesce = tx_coalesce;
else
np->tx_coalesce = 1;
macctrl = 0;
macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
macctrl |= (np->full_duplex) ? DuplexSelect : 0;
......@@ -1671,7 +1677,7 @@ rio_remove1 (struct pci_dev *pdev)
np->rx_ring_dma);
pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring,
np->tx_ring_dma);
#ifndef USE_IO_OPS
#ifdef MEM_MAPPING
iounmap ((char *) (dev->base_addr));
#endif
kfree (dev);
......
......@@ -33,15 +33,15 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#define TX_RING_SIZE 128
#define TX_QUEUE_LEN 120 /* Limit ring entries actually used. */
#define RX_RING_SIZE 128
#define TX_RING_SIZE 256
#define TX_QUEUE_LEN (TX_RING_SIZE - 1) /* Limit ring entries actually used.*/
#define RX_RING_SIZE 256
#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct netdev_desc)
#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct netdev_desc)
/* This driver was written to use PCI memory space, however x86-oriented
hardware often uses I/O space accesses. */
#ifdef USE_IO_OPS
#ifndef MEM_MAPPING
#undef readb
#undef readw
#undef readl
......@@ -658,6 +658,7 @@ struct netdev_private {
unsigned int chip_id; /* PCI table chip id */
unsigned int rx_coalesce; /* Maximum frames each RxDMAComplete intr */
unsigned int rx_timeout; /* Wait time between RxDMAComplete intr */
unsigned int tx_coalesce; /* Maximum frames each tx interrupt */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int an_enable:2; /* Auto-Negotiated Enable */
unsigned int jumbo:1; /* Jumbo frame enable */
......@@ -681,10 +682,10 @@ struct netdev_private {
};
/* The station address location in the EEPROM. */
#ifdef USE_IO_OPS
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
#else
#ifdef MEM_MAPPING
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
#else
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
#endif
/* The struct pci_device_id consist of:
vendor, device Vendor and device ID to match (or PCI_ANY_ID)
......
......@@ -39,7 +39,8 @@ struct ethtool_drvinfo {
char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
/* For PCI devices, use pci_dev->slot_name. */
char reserved1[32];
char reserved2[20];
char reserved2[16];
u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */
u32 testinfo_len;
u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
......@@ -242,6 +243,13 @@ struct ethtool_test {
u64 data[0];
};
/* for dumping NIC-specific statistics */
struct ethtool_stats {
u32 cmd; /* ETHTOOL_GSTATS */
u32 n_stats; /* number of u64's being returned */
u64 data[0];
};
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
#define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */
......@@ -272,6 +280,7 @@ struct ethtool_test {
#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */
#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */
#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */
#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
......
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