X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Ftulip%2Ftulip_core.c;h=5a35354aa523fb6dee18a02ea80b0ef558334f9b;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=6b5ba2964ac8f64cd58915952acf5c8ca68a47d3;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 6b5ba2964..5a35354aa 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1,7 +1,7 @@ /* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. */ /* - Maintained by Jeff Garzik + Maintained by Valerie Henson Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. @@ -14,13 +14,12 @@ */ -#include #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; @@ -1111,6 +1101,7 @@ static void set_rx_mode(struct net_device *dev) /* Must set DescOwned later to avoid race with chip */ dummy = entry; entry = tp->cur_tx++ % TX_RING_SIZE; + } tp->tx_buffers[entry].skb = NULL; @@ -1226,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; } @@ -1303,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 @@ -1356,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; } @@ -1368,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; @@ -1383,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 + @@ -1405,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 @@ -1489,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. */ @@ -1506,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 @@ -1564,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 @@ -1655,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) @@ -1676,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); @@ -1734,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: @@ -1749,15 +1736,23 @@ err_out_free_netdev: #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; } @@ -1765,15 +1760,29 @@ static int tulip_suspend (struct pci_dev *pdev, u32 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; } @@ -1794,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); @@ -1816,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 @@ -1844,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); }