PATCH: eepro100 fixes and updates

From: Jeff Garzik (jgarzik@mandrakesoft.com)
Date: Sun Feb 13 2000 - 10:22:42 EST


This is a COMPLETELY UNTESTED patch which updates the eepro100 driver in
2.3.44. (I have no eepro100 hardware, anybody wanna send me some? :))

Please let me know if this cures the existing problems.

Changes:
        * analyze and update eepro100 softnet logic
        * use new PCI ACPI power function
        * ditch Becker compatibility code
        * fix a few resource-related bugs

-- 
Jeff Garzik         | "Vegetarian" is the Indian word
Building 1024       | for 'lousy hunter.'
MandrakeSoft, Inc.  |

Index: drivers/net/eepro100.c =================================================================== RCS file: /g/cvslan/linux_2_3/drivers/net/eepro100.c,v retrieving revision 1.1.1.12 retrieving revision 1.1.1.12.12.1 diff -u -r1.1.1.12 -r1.1.1.12.12.1 --- drivers/net/eepro100.c 2000/02/10 22:10:24 1.1.1.12 +++ drivers/net/eepro100.c 2000/02/13 15:14:20 1.1.1.12.12.1 @@ -73,10 +73,6 @@ #include <linux/version.h> #include <linux/module.h> -#ifdef MODVERSIONS -#include <linux/modversions.h> -#endif - #include <linux/kernel.h> #include <linux/string.h> #include <linux/errno.h> @@ -84,14 +80,7 @@ #include <linux/malloc.h> #include <linux/interrupt.h> #include <linux/timer.h> -#ifdef HAS_PCI_NETIF -#include "pci-netif.h" -#else #include <linux/pci.h> -#if LINUX_VERSION_CODE < 0x20155 -#include <linux/bios32.h> /* Ignore the bogus warning in 2.1.100+ */ -#endif -#endif #include <linux/spinlock.h> #include <linux/init.h> #include <asm/bitops.h> @@ -118,26 +107,6 @@ #define RUN_AT(x) (jiffies + (x)) -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#define le16_to_cpu(val) (val) -#define cpu_to_le16(val) (val) -#define le32_to_cpu(val) (val) -#define cpu_to_le32(val) (val) -#define spin_lock_irqsave(&sp->lock, flags) save_flags(flags); cli(); -#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags); -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); -#else -#define dev_free_skb(skb) dev_kfree_skb(skb); -#endif -#if ! defined(CAP_NET_ADMIN) -#define capable(CAP_XXX) (suser()) -#endif -#if ! defined(HAS_NETIF_QUEUE) -#define netif_wake_queue(dev) mark_bh(NET_BH); -#endif /* The total I/O port extent of the board. The registers beyond 0x18 only exist on the i82558. */ @@ -278,7 +247,8 @@ */ /* This table drives the PCI probe routines. */ -static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); +static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr, + int irq, int chip_idx, int fnd_cnt); #ifdef USE_IO #define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1 @@ -288,14 +258,6 @@ #define SPEEDO_SIZE 0x1000 #endif -#if defined(HAS_PCI_NETIF) -struct pci_id_info static pci_tbl[] = { - { "Intel PCI EtherExpress Pro100", - { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE, - 0, speedo_found1 }, - {0,}, /* 0 terminated list. */ -}; -#else enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, @@ -304,13 +266,12 @@ const char *name; u16 vendor_id, device_id, device_id_mask, flags; int io_size; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt); } static pci_tbl[] = { { "Intel PCI EtherExpress Pro100", 0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 }, {0,}, /* 0 terminated list. */ }; -#endif #ifndef USE_IO #define inb readb @@ -456,7 +417,7 @@ struct enet_statistics stats; struct speedo_stats *lstats; int chip_id; - unsigned char pci_bus, pci_devfn, acpi_pwr; + unsigned char acpi_pwr; struct pci_dev *pdev; struct timer_list timer; /* Media selection timer. */ int mc_setup_frm_len; /* The length of an allocated.. */ @@ -529,65 +490,39 @@ /* A list of all installed Speedo devices, for removing the driver module. */ static struct net_device *root_speedo_dev = NULL; -#if ! defined(HAS_PCI_NETIF) -int eepro100_init(void) +static int __init eepro100_init (void) { int cards_found = 0; - static int pci_index = 0; + struct pci_dev *pdev = NULL; + long ioaddr; + int irq; - if (! pcibios_present()) - return cards_found; - - for (; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn, pci_latency; - long ioaddr; - int irq; - - u16 pci_command, new_command; - - if (pcibios_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82557, - pci_index, &pci_bus, - &pci_device_fn)) - break; -#if LINUX_VERSION_CODE >= 0x20155 || PCI_SUPPORT_1 - { - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + while ((pdev = pci_find_device (PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82557, pdev))) { #ifdef USE_IO - ioaddr = pdev->resource[1].start; + ioaddr = pdev->resource[1].start; #else - ioaddr = pdev->resource[0].start; -#endif - irq = pdev->irq; - } -#else - { - u32 pciaddr; - u8 pci_irq_line; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */ -#ifdef USE_IO - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pciaddr); - pciaddr &= ~3UL; -#else - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pciaddr); -#endif - ioaddr = pciaddr; - irq = pci_irq_line; - } + ioaddr = pdev->resource[0].start; #endif + irq = pdev->irq; + /* Remove I/O space marker in bit 0. */ #ifdef USE_IO - if (check_region(ioaddr, 32)) + if (check_region(ioaddr, 32)) { + printk(KERN_ERR "eepro100: %ld mem region busy\n", ioaddr); continue; + } #else { unsigned long orig_ioaddr = ioaddr; + + if (check_mem_region(ioaddr, 32)) { + printk(KERN_ERR "eepro100: %ld mem region busy\n", + ioaddr); + continue; + } - if ((ioaddr = (long)ioremap(ioaddr & ~0xfUL, 0x1000)) == 0) { + if ((ioaddr = (long)ioremap(orig_ioaddr, 0x1000)) == 0) { printk(KERN_INFO "Failed to map PCI address %#lx.\n", orig_ioaddr); continue; @@ -598,54 +533,30 @@ printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", ioaddr, irq); - /* Get and check the bus-master and latency values. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled this" - " device! Updating PCI command %4.4x->%4.4x.\n", - pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 32) { - printk(" PCI latency timer (CFLT) is unreasonably low at %d." - " Setting to 32 clocks.\n", pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 32); - } else if (speedo_debug > 1) - printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - - if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0,cards_found)) + if(speedo_found1(pdev, ioaddr, irq, 0,cards_found)) cards_found++; } return cards_found; } -#endif -static struct net_device *speedo_found1(int pci_bus, int pci_devfn, + +static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int card_idx) { struct net_device *dev; struct speedo_private *sp; - struct pci_dev *pdev; unsigned char *tx_ring; dma_addr_t tx_ring_dma; const char *product; int i, option; u16 eeprom[0x100]; - int acpi_idle_state = 0; + int acpi_idle_state = 0, pm; static int did_version = 0; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); - pdev = pci_find_slot(pci_bus, pci_devfn); - tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats), &tx_ring_dma); if (!tx_ring) { @@ -668,10 +579,17 @@ else option = 0; -#if defined(HAS_PCI_NETIF) - acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0); -#endif + /* save power state b4 pci_enable_device overwrites it */ + pm = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm) { + u16 pwr_command; + pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command); + acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; + } + pci_enable_device (pdev); + pci_set_master (pdev); + /* Read the station address EEPROM before doing the reset. Nominally his should even be done before accepting the device, but then we wouldn't have a device name with which to report the error. @@ -724,7 +642,7 @@ printk("%2.2X:", dev->dev_addr[i]); printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq); -#ifndef kernel_bloat +#if 1 /* OK, this is pure kernel bloat. I don't like it when other drivers waste non-pageable kernel space to emit similar messages, but I need them for bug reports. */ @@ -793,13 +711,15 @@ #endif /* kernel_bloat */ outl(PortReset, ioaddr + SCBPort); -#if defined(HAS_PCI_NETIF) + /* Return the chip to its original power state. */ - acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state); -#endif + pci_set_power_state (pdev, acpi_idle_state); - /* We do a request_region() only to register /proc/ioports info. */ +#ifdef USE_IO request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet"); +#else + request_mem_region(ioaddr, 0x1000, "Intel Speedo3 Ethernet"); +#endif dev->base_addr = ioaddr; dev->irq = irq; @@ -814,8 +734,6 @@ sp->next_module = root_speedo_dev; root_speedo_dev = dev; - sp->pci_bus = pci_bus; - sp->pci_devfn = pci_devfn; sp->pdev = pdev; sp->chip_id = chip_idx; sp->acpi_pwr = acpi_idle_state; @@ -925,13 +843,11 @@ struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; -#if defined(HAS_PCI_NETIF) - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); -#endif - if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); + pci_set_power_state(sp->pdev, 0); + /* Set up the Tx queue early.. */ sp->cur_tx = 0; sp->dirty_tx = 0; @@ -940,9 +856,9 @@ spin_lock_init(&sp->lock); /* .. we can safely take handler calls during init. */ - if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { - return -EAGAIN; - } + if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) + return -EBUSY; + MOD_INC_USE_COUNT; dev->if_port = sp->default_port; @@ -1059,6 +975,8 @@ + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD), ioaddr + SCBPointer); outw(CUStart, ioaddr + SCBCmd); + + netif_start_queue (dev); } /* Media monitoring and control. */ @@ -1220,6 +1138,7 @@ } sp->stats.tx_errors++; dev->trans_start = jiffies; + netif_start_queue (dev); return; } @@ -1230,6 +1149,8 @@ long ioaddr = dev->base_addr; int entry; + netif_stop_queue (dev); + /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -1270,13 +1191,15 @@ } if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) { sp->tx_full = 1; - netif_stop_queue(dev); } spin_unlock_irqrestore(&sp->lock, flags); } wait_for_cmd_done(ioaddr + SCBCmd); outw(CUResume, ioaddr + SCBCmd); dev->trans_start = jiffies; + + if (! sp->tx_full) + netif_start_queue (dev); return 0; } @@ -1300,6 +1223,8 @@ ioaddr = dev->base_addr; sp = (struct speedo_private *)dev->priv; + spin_lock (&sp->lock); + do { status = inw(ioaddr + SCBStatus); /* Acknowledge all of the current interrupt sources ASAP. */ @@ -1330,7 +1255,6 @@ /* User interrupt, Command/Tx unit interrupt or CU not active. */ if (status & 0xA400) { unsigned int dirty_tx; - spin_lock(&sp->lock); dirty_tx = sp->dirty_tx; while (sp->cur_tx - dirty_tx > 0) { @@ -1380,10 +1304,12 @@ && sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) { /* The ring is no longer full, clear tbusy. */ sp->tx_full = 0; - spin_unlock(&sp->lock); - netif_wake_queue(dev); - } else - spin_unlock(&sp->lock); + } + + if (sp->tx_full) + netif_stop_queue (dev); + else + netif_wake_queue (dev); } if (--boguscnt < 0) { @@ -1399,7 +1325,7 @@ printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); - return; + spin_unlock (&sp->lock); } static int @@ -1546,7 +1472,7 @@ #if LINUX_VERSION_CODE < 0x20100 skb->free = 1; #endif - dev_free_skb(skb); + dev_kfree_skb(skb); } } @@ -1559,7 +1485,7 @@ pci_unmap_single(sp->pdev, le32_to_cpu(sp->tx_ring[i].tx_buf_addr0), skb->len); - dev_free_skb(skb); + dev_kfree_skb(skb); } } if (sp->mc_setup_frm) { @@ -1571,10 +1497,9 @@ if (speedo_debug > 3) speedo_show_state(dev); -#if defined(HAS_PCI_NETIF) /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */ - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2); -#endif + pci_set_power_state (sp->pdev, 2); + MOD_DEC_USE_COUNT; return 0; @@ -1626,32 +1551,22 @@ long ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_data; int phy = sp->phy[0] & 0x1f; -#if defined(HAS_PCI_NETIF) int saved_acpi; -#endif switch(cmd) { case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ -#if defined(HAS_PCI_NETIF) - saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); - data[3] = mdio_read(ioaddr, data[0], data[1]); - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); -#else - data[3] = mdio_read(ioaddr, data[0], data[1]); -#endif + saved_acpi = pci_set_power_state (sp->pdev, 0); + data[3] = mdio_read (ioaddr, data[0], data[1]); + pci_set_power_state (sp->pdev, saved_acpi); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; -#if defined(HAS_PCI_NETIF) - saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); + saved_acpi = pci_set_power_state(sp->pdev, 0); mdio_write(ioaddr, data[0], data[1], data[2]); - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); -#else - mdio_write(ioaddr, data[0], data[1], data[2]); -#endif + pci_set_power_state(sp->pdev, saved_acpi); return 0; default: return -EOPNOTSUPP; @@ -1846,18 +1761,11 @@ if (speedo_debug) printk(KERN_INFO "%s", version); -#if defined(HAS_PCI_NETIF) - cards_found = netif_pci_probe(pci_tbl); - if (cards_found < 0) - printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); - return cards_found; -#else cards_found = eepro100_init(); if (cards_found <= 0) { printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); return -ENODEV; } -#endif return 0; } @@ -1872,11 +1780,10 @@ #ifdef USE_IO release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE); #else + release_mem_region(root_speedo_dev->base_addr, 0x1000); iounmap((char *)root_speedo_dev->base_addr); -#endif -#if defined(HAS_PCI_NETIF) - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr); #endif + pci_set_power_state(sp->pdev, sp->acpi_pwr); next_dev = sp->next_module; if (sp->priv_addr) kfree(sp->priv_addr);

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Feb 15 2000 - 21:00:24 EST