enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
struct vortex_extra_stats {
- unsigned long tx_deferred;
- unsigned long tx_multiple_collisions;
- unsigned long rx_bad_ssd;
+ unsigned long tx_deferred;
+ unsigned long tx_max_collisions;
+ unsigned long tx_multiple_collisions;
+ unsigned long tx_single_collisions;
+ unsigned long rx_bad_ssd;
};
struct vortex_private {
const char str[ETH_GSTRING_LEN];
} ethtool_stats_keys[] = {
{ "tx_deferred" },
+ { "tx_max_collisions" },
{ "tx_multiple_collisions" },
+ { "tx_single_collisions" },
{ "rx_bad_ssd" },
};
/* number of ETHTOOL_GSTATS u64's */
-#define VORTEX_NUM_STATS 3
+#define VORTEX_NUM_STATS 5
static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
int chip_idx, int card_idx);
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
/* Option count limit only -- unlimited interfaces are supported. */
#define MAX_UNITS 8
-static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = { [0 ... MAX_UNITS-1] = -1 };
+static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int use_mmio[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
static int global_options = -1;
static int global_full_duplex = -1;
static int global_enable_wol = -1;
+static int global_use_mmio = -1;
/* #define dev_alloc_skb dev_alloc_skb_debug */
module_param(compaq_irq, int, 0);
module_param(compaq_device_id, int, 0);
module_param(watchdog, int, 0);
+module_param(global_use_mmio, int, 0);
+module_param_array(use_mmio, int, NULL, 0);
MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)");
-MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if full_duplex is unset");
MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
-MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if enable_wol is unset");
MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
+MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_vortex(struct net_device *dev)
static int __devinit vortex_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int rc;
+ int rc, unit, pci_bar;
+ struct vortex_chip_info *vci;
+ void __iomem *ioaddr;
/* wake up and enable device */
rc = pci_enable_device (pdev);
if (rc < 0)
goto out;
- rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, 0, 0),
- pdev->irq, ent->driver_data, vortex_cards_found);
+ unit = vortex_cards_found;
+
+ if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) {
+ /* Determine the default if the user didn't override us */
+ vci = &vortex_info_tbl[ent->driver_data];
+ pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0;
+ } else if (unit < MAX_UNITS && use_mmio[unit] >= 0)
+ pci_bar = use_mmio[unit] ? 1 : 0;
+ else
+ pci_bar = global_use_mmio ? 1 : 0;
+
+ ioaddr = pci_iomap(pdev, pci_bar, 0);
+ if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */
+ ioaddr = pci_iomap(pdev, 0, 0);
+
+ rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq,
+ ent->driver_data, unit);
if (rc < 0) {
pci_disable_device (pdev);
goto out;
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
if (print_info) {
for (i = 0; i < 6; i++)
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
if (vp->drv_flags & EXTRA_PREAMBLE)
mii_preamble_required++;
mdio_sync(ioaddr, 32);
- mdio_read(dev, 24, 1);
+ mdio_read(dev, 24, MII_BMSR);
for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
int mii_status, phyx;
phyx = phy - 1;
else
phyx = phy;
- mii_status = mdio_read(dev, phyx, 1);
+ mii_status = mdio_read(dev, phyx, MII_BMSR);
if (mii_status && mii_status != 0xffff) {
vp->phys[phy_idx++] = phyx;
if (print_info) {
printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n");
vp->phys[0] = 24;
} else {
- vp->advertising = mdio_read(dev, vp->phys[0], 4);
+ vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE);
if (vp->full_duplex) {
/* Only advertise the FD media types. */
vp->advertising &= ~0x02A0;
if (vp->full_bus_master_tx) {
dev->hard_start_xmit = boomerang_start_xmit;
/* Actually, it still should work with iommu. */
- dev->features |= NETIF_F_SG;
- if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & HAS_HWCKSM)) ||
- (hw_checksums[card_idx] == 1)) {
- dev->features |= NETIF_F_IP_CSUM;
+ if (card_idx < MAX_UNITS &&
+ ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
+ hw_checksums[card_idx] == 1)) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
}
} else {
dev->hard_start_xmit = vortex_start_xmit;
int mii_reg1, mii_reg5;
EL3WINDOW(4);
/* Read BMSR (reg1) only to clear old status. */
- mii_reg1 = mdio_read(dev, vp->phys[0], 1);
- mii_reg5 = mdio_read(dev, vp->phys[0], 5);
+ mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
+ mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) {
netif_carrier_off(dev); /* No MII device or no link partner report */
} else {
case XCVR_MII: case XCVR_NWAY:
{
spin_lock_bh(&vp->lock);
- mii_status = mdio_read(dev, vp->phys[0], 1);
- mii_status = mdio_read(dev, vp->phys[0], 1);
+ mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
+ if (!(mii_status & BMSR_LSTATUS)) {
+ /* Re-read to get actual link status */
+ mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
+ }
ok = 1;
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
dev->name, mii_status);
if (mii_status & BMSR_LSTATUS) {
- int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
+ int mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
if (! vp->force_fd && mii_reg5 != 0xffff) {
int duplex;
iowrite8(0, ioaddr + TxStatus);
if (tx_status & 0x30) { /* txJabber or txUnderrun */
do_tx_reset = 1;
- } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */
- do_tx_reset = 1;
- reset_mask = 0x0108; /* Reset interface logic, but not download logic */
+ } else if (tx_status & 0x08) { /* maxCollisions */
+ vp->xstats.tx_max_collisions++;
+ if (vp->drv_flags & MAX_COLLISION_RESET) {
+ do_tx_reset = 1;
+ reset_mask = 0x0108; /* Reset interface logic, but not download logic */
+ }
} else { /* Merely re-enable the transmitter. */
iowrite16(TxEnable, ioaddr + EL3_CMD);
}
} else if (vortex_debug > 0)
printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
"size %d.\n", dev->name, pkt_len);
+ vp->stats.rx_dropped++;
}
- vp->stats.rx_dropped++;
issue_and_wait(dev, RxDiscard);
}
}
#if DO_ZEROCOPY
- if ( vp->rx_csumhits &&
- ((vp->drv_flags & HAS_HWCKSM) == 0) &&
- (hw_checksums[vp->card_idx] == -1)) {
- printk(KERN_WARNING "%s supports hardware checksums, and we're not using them!\n", dev->name);
+ if (vp->rx_csumhits &&
+ (vp->drv_flags & HAS_HWCKSM) == 0 &&
+ (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) {
+ printk(KERN_WARNING "%s supports hardware checksums, and we're "
+ "not using them!\n", dev->name);
}
#endif
EL3WINDOW(6);
vp->stats.tx_carrier_errors += ioread8(ioaddr + 0);
vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1);
- vp->stats.collisions += ioread8(ioaddr + 3);
vp->stats.tx_window_errors += ioread8(ioaddr + 4);
vp->stats.rx_fifo_errors += ioread8(ioaddr + 5);
vp->stats.tx_packets += ioread8(ioaddr + 6);
vp->stats.tx_bytes += ioread16(ioaddr + 12);
/* Extra stats for get_ethtool_stats() */
vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2);
+ vp->xstats.tx_single_collisions += ioread8(ioaddr + 3);
vp->xstats.tx_deferred += ioread8(ioaddr + 8);
EL3WINDOW(4);
vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12);
+ vp->stats.collisions = vp->xstats.tx_multiple_collisions
+ + vp->xstats.tx_single_collisions
+ + vp->xstats.tx_max_collisions;
+
{
u8 up = ioread8(ioaddr + 13);
vp->stats.rx_bytes += (up & 0x0f) << 16;
spin_unlock_irqrestore(&vp->lock, flags);
data[0] = vp->xstats.tx_deferred;
- data[1] = vp->xstats.tx_multiple_collisions;
- data[2] = vp->xstats.rx_bad_ssd;
+ data[1] = vp->xstats.tx_max_collisions;
+ data[2] = vp->xstats.tx_multiple_collisions;
+ data[3] = vp->xstats.tx_single_collisions;
+ data[4] = vp->xstats.rx_bad_ssd;
}
.set_settings = vortex_set_settings,
.get_link = vortex_get_link,
.nway_reset = vortex_nway_reset,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
#ifdef CONFIG_PCI