summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-06-18 07:55:25 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-06-18 07:55:25 -0700
commit7ca66affe7bcbf1d2d16f0cd531e1b8bdd97f08c (patch)
treefde83fe5427afb16667bd69b349ed33b815942a9 /drivers
parent33e448ef667e99120f43e0bbc656edc4df667e89 (diff)
parentc1bc73b5ef036d5ddba70e2695877cdebb6b6ff0 (diff)
Merge http://gkernel.bkbits.net/net-drivers-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/8139cp.c143
-rw-r--r--drivers/net/dl2k.c26
-rw-r--r--drivers/net/dl2k.h15
3 files changed, 162 insertions, 22 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index f26a591369aa..d591b962b06b 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -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 @@ err_out_gregs:
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;
}
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 76d6a4260b3f..aa6e13a6788c 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -1,6 +1,6 @@
/* 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);
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index a3e3b30fc207..3108493bd048 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -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)