Merge branch 'intx' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[pandora-kernel.git] / drivers / net / tulip / tulip_core.c
index e1987ec..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.
 
@@ -17,9 +17,9 @@
 
 #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"
 
@@ -130,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.
@@ -144,59 +151,60 @@ 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 },
 
 };
 
@@ -295,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)
@@ -522,20 +532,9 @@ static void tulip_tx_timeout(struct net_device *dev)
                           "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",
@@ -575,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);
@@ -732,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);
@@ -841,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
 };
 
@@ -1023,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;
@@ -1361,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;
 
@@ -1376,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 +
@@ -1398,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
@@ -1552,7 +1546,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                if (pcp) {
                        unsigned char *addr;
                        int len;
-                 
+
                        addr = of_get_property(pcp->prom_node,
                                               "local-mac-address", &len);
                        if (addr && len == 6)
@@ -1644,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)
@@ -1768,7 +1768,10 @@ static int tulip_resume(struct pci_dev *pdev)
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 
-       pci_enable_device(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");
@@ -1821,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