fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / tulip / tulip_core.c
index e0ae3ed..5a35354 100644 (file)
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -131,7 +130,14 @@ int tulip_debug = TULIP_DEBUG;
 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.
@@ -145,63 +151,61 @@ struct tulip_chip_table tulip_tbl[] = {
 
   /* 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 },
 };
 
 
@@ -239,9 +243,9 @@ static struct pci_device_id tulip_pci_tbl[] = {
        { 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);
@@ -299,12 +303,14 @@ static void tulip_up(struct net_device *dev)
 
        /* 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)
@@ -493,7 +499,7 @@ tulip_open(struct net_device *dev)
 {
        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);
@@ -521,25 +527,14 @@ static void tulip_tx_timeout(struct net_device *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",
@@ -579,14 +574,9 @@ static void tulip_tx_timeout(struct net_device *dev)
        }
 #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);
@@ -624,7 +614,7 @@ static void tulip_init_ring(struct net_device *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. */
@@ -736,6 +726,8 @@ static void tulip_down (struct net_device *dev)
        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);
@@ -845,7 +837,7 @@ static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in
        strcpy(info->bus_info, pci_name(np->pdev));
 }
 
-static struct ethtool_ops ops = {
+static const struct ethtool_ops ops = {
        .get_drvinfo = tulip_get_drvinfo
 };
 
@@ -1027,8 +1019,6 @@ static void set_rx_mode(struct net_device *dev)
        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;
@@ -1102,18 +1092,16 @@ static void set_rx_mode(struct net_device *dev)
                        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;
@@ -1229,15 +1217,11 @@ out:
  *     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;
 }
 
@@ -1306,7 +1290,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
         */
 
        /* 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
@@ -1359,10 +1343,10 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        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;
        }
 
@@ -1371,11 +1355,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        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;
 
@@ -1386,6 +1367,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
         * 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 +
@@ -1408,6 +1390,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        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
@@ -1492,14 +1476,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                        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. */
@@ -1509,13 +1485,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                }
 #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
@@ -1567,13 +1543,17 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                        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
@@ -1658,8 +1638,14 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        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)
@@ -1679,7 +1665,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
        switch (chip_idx) {
        case DC21140:
        case DM910X:
-       case ULI526X:
        default:
                if (tp->mtable)
                        iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
@@ -1737,8 +1722,7 @@ err_out_free_ring:
                             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:
@@ -1756,11 +1740,19 @@ 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;
 }
 
@@ -1768,15 +1760,29 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
 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;
 }
 
@@ -1797,8 +1803,7 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
                             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);
@@ -1819,7 +1824,7 @@ static void poll_tulip (struct net_device *dev)
        /* 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
@@ -1847,7 +1852,7 @@ static int __init tulip_init (void)
        tulip_max_interrupt_work = max_interrupt_work;
 
        /* probe for and init boards */
-       return pci_module_init (&tulip_driver);
+       return pci_register_driver(&tulip_driver);
 }