/* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. */
/*
- Maintained by Jeff Garzik <jgarzik@pobox.com>
+ Maintained by Valerie Henson <val_henson@linux.intel.com>
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
*/
-#include <linux/config.h>
#define DRV_NAME "tulip"
#ifdef CONFIG_TULIP_NAPI
-#define DRV_VERSION "1.1.13-NAPI" /* Keep at least for test */
+#define DRV_VERSION "1.1.14-NAPI" /* Keep at least for test */
#else
-#define DRV_VERSION "1.1.13"
+#define DRV_VERSION "1.1.14"
#endif
#define DRV_RELDATE "May 11, 2002"
ToDo: Non-Intel setting could be better.
*/
-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__ia64__)
static int csr0 = 0x01A00000 | 0xE000;
-#elif defined(__i386__) || defined(__powerpc__)
+#elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__)
static int csr0 = 0x01A00000 | 0x8000;
#elif defined(__sparc__) || defined(__hppa__)
/* The UltraSparc PCI controllers will disconnect at every 64-byte
MODULE_AUTHOR("The Linux Kernel Team");
MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(tulip_debug, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(csr0, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_VERSION(DRV_VERSION);
+module_param(tulip_debug, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param(csr0, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
#define PFX DRV_NAME ": "
int tulip_debug = 1;
#endif
+static void tulip_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = netdev_priv(dev);
+ if (netif_running(dev))
+ schedule_work(&tp->media_work);
+}
/*
* This table use during operation for capabilities and media timer.
/* DC21140 */
{ "Digital DS21140 Tulip", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer },
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer,
+ tulip_media_task },
/* DC21142, DC21143 */
- { "Digital DS21143 Tulip", 128, 0x0801fbff,
+ { "Digital DS21142/43 Tulip", 128, 0x0801fbff,
HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY
- | HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer },
+ | HAS_INTR_MITIGATION | HAS_PCI_MWI, tulip_timer, t21142_media_task },
/* LC82C168 */
{ "Lite-On 82c168 PNIC", 256, 0x0001fbef,
- HAS_MII | HAS_PNICNWAY, pnic_timer },
+ HAS_MII | HAS_PNICNWAY, pnic_timer, },
/* MX98713 */
{ "Macronix 98713 PMAC", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
/* MX98715 */
{ "Macronix 98715 PMAC", 256, 0x0001ebef,
- HAS_MEDIA_TABLE, mxic_timer },
+ HAS_MEDIA_TABLE, mxic_timer, },
/* MX98725 */
{ "Macronix 98725 PMAC", 256, 0x0001ebef,
- HAS_MEDIA_TABLE, mxic_timer },
+ HAS_MEDIA_TABLE, mxic_timer, },
/* AX88140 */
{ "ASIX AX88140", 128, 0x0001fbff,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
- | IS_ASIX, tulip_timer },
+ | IS_ASIX, tulip_timer, tulip_media_task },
/* PNIC2 */
{ "Lite-On PNIC-II", 256, 0x0801fbff,
- HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer },
+ HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer, },
/* COMET */
{ "ADMtek Comet", 256, 0x0001abef,
- HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer },
+ HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer, },
/* COMPEX9881 */
{ "Compex 9881 PMAC", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
/* I21145 */
{ "Intel DS21145 Tulip", 128, 0x0801fbff,
HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI
- | HAS_NWAY | HAS_PCI_MWI, t21142_timer },
+ | HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task },
/* DM910X */
{ "Davicom DM9102/DM9102A", 128, 0x0001ebef,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
- tulip_timer },
+ tulip_timer, tulip_media_task },
/* RS7112 */
{ "Conexant LANfinity", 256, 0x0001ebef,
- HAS_MII | HAS_ACPI, tulip_timer },
+ HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task },
- /* ULi526X */
- { "ULi M5261/M5263", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
};
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x1186, 0x1591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
{ 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
- { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
- { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
+ { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+ { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
iowrite32(0x00000001, ioaddr + CSR0);
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, &i); /* flush write */
udelay(100);
/* Deassert reset.
Wait the specified 50 PCI cycles after a reset by initializing
Tx and Rx queues and the address filter list. */
iowrite32(tp->csr0, ioaddr + CSR0);
+ pci_read_config_dword(tp->pdev, PCI_COMMAND, &i); /* flush write */
udelay(100);
if (tulip_debug > 1)
{
int retval;
- if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)))
+ if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev)))
return retval;
tulip_init_ring (dev);
dev->name);
} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
|| tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
- || tp->chip_id == DM910X || tp->chip_id == ULI526X) {
+ || tp->chip_id == DM910X) {
printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
"SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15));
- if ( ! tp->medialock && tp->mtable) {
- do
- --tp->cur_index;
- while (tp->cur_index >= 0
- && (tulip_media_cap[tp->mtable->mleaf[tp->cur_index].media]
- & MediaIsFD));
- if (--tp->cur_index < 0) {
- /* We start again, but should instead look for default. */
- tp->cur_index = tp->mtable->leafcount - 1;
- }
- tulip_select_media(dev, 0);
- printk(KERN_WARNING "%s: transmit timed out, switching to %s "
- "media.\n", dev->name, medianame[dev->if_port]);
- }
+ tp->timeout_recovery = 1;
+ schedule_work(&tp->media_work);
+ goto out_unlock;
} else if (tp->chip_id == PNIC2) {
printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, "
"CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n",
}
#endif
- /* Stop and restart the chip's Tx processes . */
-
- tulip_restart_rxtx(tp);
- /* Trigger an immediate transmit demand. */
- iowrite32(0, ioaddr + CSR1);
-
- tp->stats.tx_errors++;
+ tulip_tx_timeout_complete(tp, ioaddr);
+out_unlock:
spin_unlock_irqrestore (&tp->lock, flags);
dev->trans_start = jiffies;
netif_wake_queue (dev);
tp->rx_buffers[i].skb = skb;
if (skb == NULL)
break;
- mapping = pci_map_single(tp->pdev, skb->tail,
+ mapping = pci_map_single(tp->pdev, skb->data,
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
tp->rx_buffers[i].mapping = mapping;
skb->dev = dev; /* Mark as being used by this device. */
void __iomem *ioaddr = tp->base_addr;
unsigned long flags;
+ flush_scheduled_work();
+
del_timer_sync (&tp->timer);
#ifdef CONFIG_TULIP_NAPI
del_timer_sync (&tp->oom_timer);
strcpy(info->bus_info, pci_name(np->pdev));
}
-static struct ethtool_ops ops = {
+static const struct ethtool_ops ops = {
.get_drvinfo = tulip_get_drvinfo
};
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
tp->csr6 |= AcceptAllMulticast | AcceptAllPhys;
csr6 |= AcceptAllMulticast | AcceptAllPhys;
- /* Unconditionally log net taps. */
- printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
} else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
/* Too many to filter well -- accept all multicasts. */
tp->csr6 |= AcceptAllMulticast;
else
filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
filterbit &= 0x3f;
- mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31));
+ mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
if (tulip_debug > 2) {
printk(KERN_INFO "%s: Added filter for %2.2x:%2.2x:%2.2x:"
"%2.2x:%2.2x:%2.2x %8.8x bit %d.\n", dev->name,
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
- /* Avoid a chip errata by prefixing a dummy entry. Don't do
- this on the ULI526X as it triggers a different problem */
- if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
- tp->tx_buffers[entry].skb = NULL;
- tp->tx_buffers[entry].mapping = 0;
- tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
- tp->tx_ring[entry].buffer1 = 0;
- /* Must set DescOwned later to avoid race with chip */
- dummy = entry;
- entry = tp->cur_tx++ % TX_RING_SIZE;
- }
+ /* Avoid a chip errata by prefixing a dummy entry. */
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ /* Must set DescOwned later to avoid race with chip */
+ dummy = entry;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+
}
tp->tx_buffers[entry].skb = NULL;
* Chips that have the MRM/reserved bit quirk and the burst quirk. That
* is the DM910X and the on chip ULi devices
*/
-
+
static int tulip_uli_dm_quirk(struct pci_dev *pdev)
{
if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
- return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
- return 1;
return 0;
}
*/
/* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
- aligned. Aries might need this too. The Saturn errata are not
+ aligned. Aries might need this too. The Saturn errata are not
pretty reading but thankfully it's an old 486 chipset.
2. The dreaded SiS496 486 chipset. Same workaround as Intel
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
- printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, "
+ printk (KERN_ERR PFX "%s: I/O region (0x%llx@0x%llx) too small, "
"aborting\n", pci_name(pdev),
- pci_resource_len (pdev, 0),
- pci_resource_start (pdev, 0));
+ (unsigned long long)pci_resource_len (pdev, 0),
+ (unsigned long long)pci_resource_start (pdev, 0));
goto err_out_free_netdev;
}
if (pci_request_regions (pdev, "tulip"))
goto err_out_free_netdev;
-#ifndef USE_IO_OPS
- ioaddr = pci_iomap(pdev, 1, tulip_tbl[chip_idx].io_size);
-#else
- ioaddr = pci_iomap(pdev, 0, tulip_tbl[chip_idx].io_size);
-#endif
+ ioaddr = pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size);
+
if (!ioaddr)
goto err_out_free_res;
* it is zeroed and aligned in alloc_etherdev
*/
tp = netdev_priv(dev);
+ tp->dev = dev;
tp->rx_ring = pci_alloc_consistent(pdev,
sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
tp->timer.data = (unsigned long)dev;
tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
+ INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task);
+
dev->base_addr = (unsigned long)ioaddr;
#ifdef CONFIG_TULIP_MWI
sa_offset = 2; /* Grrr, damn Matrox boards. */
multiport_cnt = 4;
}
-#ifdef CONFIG_DDB5476
- if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) {
- /* DDB5476 MAC address in first EEPROM locations. */
- sa_offset = 0;
- /* No media table either */
- tp->flags &= ~HAS_MEDIA_TABLE;
- }
-#endif
#ifdef CONFIG_DDB5477
if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) {
/* DDB5477 MAC address in first EEPROM locations. */
}
#endif
#ifdef CONFIG_MIPS_COBALT
- if ((pdev->bus->number == 0) &&
+ if ((pdev->bus->number == 0) &&
((PCI_SLOT(pdev->devfn) == 7) ||
(PCI_SLOT(pdev->devfn) == 12))) {
/* Cobalt MAC address in first EEPROM locations. */
sa_offset = 0;
- /* No media table either */
- tp->flags &= ~HAS_MEDIA_TABLE;
+ /* Ensure our media table fixup get's applied */
+ memcpy(ee_data + 16, ee_data, 8);
}
#endif
#ifdef CONFIG_GSC
dev->dev_addr[i] = last_phys_addr[i];
dev->dev_addr[i] = last_phys_addr[i] + 1;
#if defined(__sparc__)
- if ((pcp != NULL) && prom_getproplen(pcp->prom_node,
- "local-mac-address") == 6) {
- prom_getproperty(pcp->prom_node, "local-mac-address",
- dev->dev_addr, 6);
+ if (pcp) {
+ unsigned char *addr;
+ int len;
+
+ addr = of_get_property(pcp->prom_node,
+ "local-mac-address", &len);
+ if (addr && len == 6)
+ memcpy(dev->dev_addr, addr, 6);
}
#endif
-#if defined(__i386__) /* Patch up x86 BIOS bug. */
+#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */
if (last_irq)
irq = last_irq;
#endif
if (register_netdev(dev))
goto err_out_free_ring;
- printk(KERN_INFO "%s: %s rev %d at %p,",
- dev->name, chip_name, chip_rev, ioaddr);
+ printk(KERN_INFO "%s: %s rev %d at "
+#ifdef CONFIG_TULIP_MMIO
+ "MMIO"
+#else
+ "Port"
+#endif
+ " %#llx,", dev->name, chip_name, chip_rev,
+ (unsigned long long) pci_resource_start(pdev, TULIP_BAR));
pci_set_drvdata(pdev, dev);
if (eeprom_missing)
switch (chip_idx) {
case DC21140:
case DM910X:
- case ULI526X:
default:
if (tp->mtable)
iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
tp->rx_ring, tp->rx_ring_dma);
err_out_mtable:
- if (tp->mtable)
- kfree (tp->mtable);
+ kfree (tp->mtable);
pci_iounmap(pdev, ioaddr);
err_out_free_res:
#ifdef CONFIG_PM
-static int tulip_suspend (struct pci_dev *pdev, u32 state)
+static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (dev && netif_running (dev) && netif_device_present (dev)) {
- netif_device_detach (dev);
- tulip_down (dev);
- /* pci_power_off(pdev, -1); */
- }
+ if (!dev)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ tulip_down(dev);
+
+ netif_device_detach(dev);
+ free_irq(dev->irq, dev);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
return 0;
}
static int tulip_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ int retval;
- if (dev && netif_running (dev) && !netif_device_present (dev)) {
-#if 1
- pci_enable_device (pdev);
-#endif
- /* pci_power_on(pdev); */
- tulip_up (dev);
- netif_device_attach (dev);
+ if (!dev)
+ return -EINVAL;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if ((retval = pci_enable_device(pdev))) {
+ printk (KERN_ERR "tulip: pci_enable_device failed in resume\n");
+ return retval;
}
+
+ if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) {
+ printk (KERN_ERR "tulip: request_irq failed in resume\n");
+ return retval;
+ }
+
+ netif_device_attach(dev);
+
+ if (netif_running(dev))
+ tulip_up(dev);
+
return 0;
}
sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
tp->rx_ring, tp->rx_ring_dma);
- if (tp->mtable)
- kfree (tp->mtable);
+ kfree (tp->mtable);
pci_iounmap(pdev, tp->base_addr);
free_netdev (dev);
pci_release_regions (pdev);
/* disable_irq here is not very nice, but with the lockless
interrupt handler we have no other choice. */
disable_irq(dev->irq);
- tulip_interrupt (dev->irq, dev, NULL);
+ tulip_interrupt (dev->irq, dev);
enable_irq(dev->irq);
}
#endif
tulip_max_interrupt_work = max_interrupt_work;
/* probe for and init boards */
- return pci_module_init (&tulip_driver);
+ return pci_register_driver(&tulip_driver);
}