Index: oldkernel/linux/drivers/net/eepro100.c diff -u linux/drivers/net/eepro100.c:1.2 linux/drivers/net/eepro100.c:1.3 --- linux/drivers/net/eepro100.c:1.2 Thu Jun 1 15:32:59 2000 +++ linux/drivers/net/eepro100.c Thu Jun 1 16:52:50 2000 @@ -1,14 +1,14 @@ -/* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. */ +/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */ /* NOTICE: this version tested with kernels 1.3.72 and later only! - Written 1996-1998 by Donald Becker. + Written 1996-1999 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. - This driver is for the Intel EtherExpress Pro 100B boards. - It should work with other i82557 and i82558 boards. - To use a built-in driver, install as drivers/net/eepro100.c. + This driver is for the Intel EtherExpress Pro100 (Speedo3) design. + It should work with all i82557/558/559 boards. + To use as a module, use the compile-command at the end of the file. The author may be reached as becker@CESDIS.usra.edu, or C/O @@ -16,15 +16,23 @@ Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 For updates see http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html - There is also a mailing list based at + For installation instructions + http://cesdis.gsfc.nasa.gov/linux/misc/modules.html + There is a Majordomo mailing list based at linux-eepro100@cesdis.gsfc.nasa.gov + + This driver also contains updates by Andrey Savochkin and others. + For this specific driver variant please use linux-kernel for + bug reports. + */ static const char *version = -"eepro100.c:v1.06 10/16/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"; +"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" +"eepro100.c: $Revision: 1.18 $ 1999/12/29 Modified by Andrey V. Savochkin \n"; /* A few user-configurable values that apply to all boards. - First set are undocumented and spelled per Intel recommendations. */ + First set is undocumented and spelled per Intel recommendations. */ static int congenb = 0; /* Enable congestion control in the DP83840. */ static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ @@ -43,14 +51,52 @@ #endif /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 200; +static int max_interrupt_work = 20; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */ static int multicast_filter_limit = 64; -#include +/* 'options' is used to pass a transceiver override or full-duplex flag + e.g. "options=16" for FD, "options=32" for 100mbps-only. */ +static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +#ifdef MODULE +static int debug = -1; /* The debug level */ +#endif + +/* A few values that may be tweaked. */ +/* The ring sizes should be a power of two for efficiency. */ +#define TX_RING_SIZE 32 +#define RX_RING_SIZE 32 +/* How much slots multicast filter setup may take. + Do not descrease without changing set_rx_mode() implementaion. */ +#define TX_MULTICAST_SIZE 2 +#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2) +/* Actual number of TX packets queued, must be + <= TX_RING_SIZE-TX_MULTICAST_RESERV. */ +#define TX_QUEUE_LIMIT (TX_RING_SIZE-TX_MULTICAST_RESERV) +/* Hysteresis marking queue as no longer full. */ +#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4) +/* Operational parameters that usually are not changed. */ + +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (2*HZ) +/* Size of an pre-allocated Rx buffer: + slack.*/ +#define PKT_BUF_SZ 1536 + +#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + #include +#include +#if defined(MODVERSIONS) +#include +#endif + #include #include #include @@ -58,19 +104,27 @@ #include #include #include +#ifdef HAS_PCI_NETIF +#include "pci-netif.h" +#else #include +#endif +#include +#if LINUX_VERSION_CODE >= 0x20312 +#include +#else +#include +#endif + +#include +#include + #include #include #include #include - -#include -#include -#include -/* - * Module documentation - */ +#if defined(MODULE) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver"); MODULE_PARM(debug, "i"); @@ -84,16 +138,35 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(multicast_filter_limit, "i"); +#endif #define RUN_AT(x) (jiffies + (x)) +/* Condensed bus+endian portability operations. */ +#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) +#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) + +#if LINUX_VERSION_CODE < 0x020314 +#define net_device device +#define pci_base_address(p, n) (p)->base_address[n] +#else +#define pci_base_address(p, n) (p)->resource[n].start +#endif -#define dev_free_skb(skb) dev_kfree_skb(skb); +#define dev_free_skb(skb) dev_kfree_skb(skb); +#if ! defined(HAS_NETIF_QUEUE) +#define netif_wake_queue(dev) do { \ + clear_bit(0, (void*)&dev->tbusy); \ + mark_bh(NET_BH); \ + } while(0) +#define netif_start_queue(dev) clear_bit(0, (void*)&dev->tbusy) +#define netif_stop_queue(dev) set_bit(0, (void*)&dev->tbusy) +#endif /* The total I/O port extent of the board. The registers beyond 0x18 only exist on the i82558. */ #define SPEEDO3_TOTAL_SIZE 0x20 -int speedo_debug = 0; +int speedo_debug = 1; /* Theory of Operation @@ -201,24 +274,6 @@ is non-trivial, and the larger copy might flush the cache of useful data, so we pass up the skbuff the packet was received into. -IIID. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'sp->tx_full' flag. - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so -we can't avoid the interrupt overhead by having the Tx routine reap the Tx -stats.) After reaping the stats, it marks the queue entry as empty by setting -the 'base' to zero. Iff the 'sp->tx_full' flag is set, it clears both the -tx_full and tbusy flags. - IV. Notes Thanks to Steve Williams of Intel for arranging the non-disclosure agreement @@ -227,16 +282,56 @@ */ -/* A few values that may be tweaked. */ -/* The ring sizes should be a power of two for efficiency. */ -#define TX_RING_SIZE 16 /* Effectively 2 entries fewer. */ -#define RX_RING_SIZE 16 -/* Size of an pre-allocated Rx buffer: + slack.*/ -#define PKT_BUF_SZ 1536 +/* 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); -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT ((800*HZ)/1000) +#ifdef USE_IO +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1 +#define SPEEDO_SIZE 32 +#else +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0 +#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, +}; +struct pci_id_info { + 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); +} 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 +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl +#define inb readb +#define inw readw +#define inl readl +#define outb writeb +#define outw writew +#define outl writel +#endif + /* How to wait for the command unit to accept a command. Typically this takes 0 ticks. */ static inline void wait_for_cmd_done(long cmd_ioaddr) @@ -246,10 +341,6 @@ while(inb(cmd_ioaddr) && --wait >= 0); } -/* Operational parameter that usually are not changed. */ - -/* The rest of these values should never change. */ - /* Offsets to the various registers. All accesses need not be longword aligned. */ enum speedo_offsets { @@ -262,34 +353,48 @@ }; /* Commands that can be put in a command list entry. */ enum commands { - CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7, - CmdSuspend = 0x4000, /* Suspend after completion. */ - CmdIntr = 0x2000, /* Interrupt after completion. */ - CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ + CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000, + CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000, + CmdDump = 0x60000, CmdDiagnose = 0x70000, + CmdSuspend = 0x40000000, /* Suspend after completion. */ + CmdIntr = 0x20000000, /* Interrupt after completion. */ + CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */ }; +/* Clear CmdSuspend (1<<30) atomically. + Otherwise the command status in the lower 16 bits may be reset after + an asynchronous change. Previous driver version used separate 16 bit fields + for commands and statuses. --SAW + */ +#ifdef __i386__ +#define speedo_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) +#define speedo_clear_mask(mask, addr) \ +__asm__ __volatile__("lock; andl %0,%1" \ +: : "r" (~(mask)),"m" (speedo_fool_gcc(addr)) : "memory") +#define clear_suspend(cmd) speedo_clear_mask(CmdSuspend, &(cmd)->cmd_status) +#else +#define clear_suspend(cmd) (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend) +#endif + +enum SCBCmdBits { + SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000, + SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400, + SCBTriggerIntr=0x0200, SCBMaskAll=0x0100, + /* The rest are Rx and Tx commands. */ + CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050, + CUCmdBase=0x0060, /* CU Base address (set to zero) . */ + CUDumpStats=0x0070, /* Dump then reset stats counters. */ + RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006, + RxResumeNoResources=0x0007, +}; -/* The SCB accepts the following controls for the Tx and Rx units: */ -#define CU_START 0x0010 -#define CU_RESUME 0x0020 -#define CU_STATSADDR 0x0040 -#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ -#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */ -#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ - -#define RX_START 0x0001 -#define RX_RESUME 0x0002 -#define RX_ABORT 0x0004 -#define RX_ADDR_LOAD 0x0006 -#define RX_RESUMENR 0x0007 -#define INT_MASK 0x0100 -#define DRVR_INT 0x0200 /* Driver generated interrupt. */ +enum SCBPort_cmds { + PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3, +}; /* The Speedo3 Rx and Tx frame/buffer descriptors. */ -struct descriptor { /* A generic descriptor. */ - s16 status; /* Offset 0. */ - s16 command; /* Offset 2. */ - u32 link; /* struct descriptor * */ +struct descriptor { /* A generic descriptor. */ + s32 cmd_status; /* All command and status fields. */ + u32 link; /* struct descriptor * */ unsigned char params[0]; }; @@ -298,8 +403,7 @@ s32 status; u32 link; /* struct RxFD * */ u32 rx_buf_addr; /* void * */ - u16 count; - u16 size; + u32 count; }; /* Selected elements of the Tx/RxFD.status word. */ @@ -307,7 +411,7 @@ RxComplete=0x8000, RxOK=0x2000, RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010, RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002, - StatusComplete=0x8000, + TxUnderrun=0x1000, StatusComplete=0x8000, }; struct TxFD { /* Transmit frame descriptor set. */ @@ -322,6 +426,14 @@ s32 tx_buf_size1; /* Length of Tx frame. */ }; +/* Multicast filter setting block. --SAW */ +struct speedo_mc_block { + struct speedo_mc_block *next; + unsigned int tx; + char fill[16 - sizeof(struct speedo_mc_block *) - sizeof(unsigned int)]; + struct descriptor frame; +}; + /* Elements of the dump_statistics block. This block must be lword aligned. */ struct speedo_stats { u32 tx_good_frames; @@ -343,49 +455,60 @@ u32 done_marker; }; +enum Rx_ring_state_bits { + RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8, +}; + +/* Do not change the position (alignment) of the first few elements! + The later elements are grouped for cache locality. */ struct speedo_private { - char devname[8]; /* Used only for kernel debugging. */ - const char *product_name; - struct device *next_module; - spinlock_t lock; - struct TxFD tx_ring[TX_RING_SIZE] /* Commands (usually CmdTxPacket). */ - __attribute__ ((aligned (L1_CACHE_BYTES)));; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct TxFD tx_ring[TX_RING_SIZE]; /* Commands (usually CmdTxPacket). */ + struct RxFD *rx_ringp[RX_RING_SIZE]; /* Rx descriptor, used as ring. */ + /* The addresses of a Tx/Rx-in-place packets/buffers. */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; - struct descriptor *last_cmd; /* Last command sent. */ - /* Rx descriptor ring & addresses of receive-in-place skbuffs. */ - struct RxFD *rx_ringp[RX_RING_SIZE]; struct sk_buff* rx_skbuff[RX_RING_SIZE]; + struct descriptor *last_cmd; /* Last command sent. */ + unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */ + spinlock_t lock; /* Group with Tx control cache line. */ + u32 tx_threshold; /* The value for txdesc.count. */ struct RxFD *last_rxf; /* Last command sent. */ + unsigned int cur_rx, dirty_rx; /* The next free ring entry */ + long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ + const char *product_name; + struct net_device *next_module; + void *priv_addr; /* Unaligned address for kfree */ struct enet_statistics stats; struct speedo_stats lstats; + int chip_id; + unsigned char pci_bus, pci_devfn, acpi_pwr; struct timer_list timer; /* Media selection timer. */ - long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - int mc_setup_frm_len; /* The length of an allocated.. */ - struct descriptor *mc_setup_frm; /* ..multicast setup frame. */ - int mc_setup_busy; /* Avoid double-use of setup frame. */ + struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */ + struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */ + int in_interrupt; /* Word-aligned dev->interrupt */ char rx_mode; /* Current PROMISC/ALLMULTI setting. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int default_port:1; /* Last dev->if_port value. */ + unsigned int flow_ctrl:1; /* Use 802.3x flow control. */ unsigned int rx_bug:1; /* Work around receiver hang errata. */ unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */ unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */ + unsigned char default_port:8; /* Last dev->if_port value. */ + unsigned char rx_ring_state; /* RX ring status flags. */ unsigned short phy[2]; /* PHY media interfaces available. */ + unsigned short advertising; /* Current PHY advertised caps. */ + unsigned short partner; /* Link partner caps. */ }; /* The parameters for a CmdConfigure operation. There are so many options that it would be difficult to document each bit. We mostly use the default or recommended settings. */ const char i82557_config_cmd[22] = { - 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 0x3f, 0x05, }; const char i82558_config_cmd[22] = { - 22, 0x08, 0, 1, 0, 0x80, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0x08, 0x88, 0x68, 0, 0x40, 0xf2, 0xBD, /* 0xBD->0xFD=Force full-duplex */ 0x31, 0x05, }; @@ -399,35 +522,29 @@ enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240, S80C24, I82555, DP83840A=10, }; static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 }; +#define EE_READ_CMD (6) -static void speedo_found1(struct device *dev, long ioaddr, int irq, - int card_idx); - -static int read_eeprom(long ioaddr, int location, int addr_len); +static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); static int mdio_write(long ioaddr, int phy_id, int location, int value); -static int speedo_open(struct device *dev); +static int speedo_open(struct net_device *dev); +static void speedo_resume(struct net_device *dev); static void speedo_timer(unsigned long data); -static void speedo_init_rx_ring(struct device *dev); -static int speedo_start_xmit(struct sk_buff *skb, struct device *dev); -static int speedo_rx(struct device *dev); +static void speedo_init_rx_ring(struct net_device *dev); +static void speedo_tx_timeout(struct net_device *dev); +static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void speedo_refill_rx_buffers(struct net_device *dev, int force); +static int speedo_rx(struct net_device *dev); +static void speedo_tx_buffer_gc(struct net_device *dev); static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static int speedo_close(struct device *dev); -static struct enet_statistics *speedo_get_stats(struct device *dev); -static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd); -static void set_rx_mode(struct device *dev); +static int speedo_close(struct net_device *dev); +static struct enet_statistics *speedo_get_stats(struct net_device *dev); +static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static void set_rx_mode(struct net_device *dev); +static void speedo_show_state(struct net_device *dev); -/* The parameters that may be passed in... */ -/* 'options' is used to pass a transceiver override or full-duplex flag - e.g. "options=16" for FD, "options=32" for 100mbps-only. */ -static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#ifdef MODULE -static int debug = -1; /* The debug level */ -#endif - #ifdef honor_default_port /* Optional driver feature to allow forcing the transceiver setting. Not recommended. */ @@ -436,9 +553,10 @@ #endif /* A list of all installed Speedo devices, for removing the driver module. */ -static struct device *root_speedo_dev = NULL; +static struct net_device *root_speedo_dev = NULL; -int eepro100_init(struct device *dev) +#if ! defined(HAS_PCI_NETIF) +int eepro100_init(void) { int cards_found = 0; static int pci_index = 0; @@ -448,6 +566,7 @@ for (; pci_index < 8; pci_index++) { unsigned char pci_bus, pci_device_fn, pci_latency; + u32 pciaddr; long ioaddr; int irq; @@ -460,11 +579,23 @@ break; { struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->base_address[1]; /* Use [0] to mem-map */ +#ifdef USE_IO + pciaddr = pci_base_address(pdev, 1); /* Use [0] to mem-map */ +#else + pciaddr = pci_base_address(pdev, 0); +#endif irq = pdev->irq; } /* Remove I/O space marker in bit 0. */ - ioaddr &= ~3UL; + if (pciaddr & 1) { + ioaddr = pciaddr & ~3UL; + if (check_region(ioaddr, 32)) + continue; + } else if ((ioaddr = (long)ioremap(pciaddr & ~0xfUL, 0x1000)) == 0) { + printk(KERN_INFO "Failed to map PCI address %#x.\n", + pciaddr); + continue; + } if (speedo_debug > 2) printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", ioaddr, irq); @@ -490,27 +621,78 @@ } else if (speedo_debug > 1) printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - speedo_found1(dev, ioaddr, irq, cards_found); - dev = NULL; - cards_found++; + if (speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0, cards_found)) + 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_82559ER, + pci_index, &pci_bus, + &pci_device_fn)) + break; + { + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->base_address[1]; /* Use [0] to mem-map */ + irq = pdev->irq; + } + /* Remove I/O space marker in bit 0. */ + ioaddr &= ~3; + if (speedo_debug > 2) + printk("Found Intel i82559ER 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)) + cards_found++; + } + return cards_found; } +#endif -static void speedo_found1(struct device *dev, long ioaddr, int irq, - int card_idx) +static struct net_device *speedo_found1(int pci_bus, int pci_devfn, + long ioaddr, int irq, int chip_idx, int card_idx) { - static int did_version = 0; /* Already printed version info. */ + struct net_device *dev; struct speedo_private *sp; - char *product; + const char *product; int i, option; - u16 eeprom[0x40]; - + u16 eeprom[0x100]; + int acpi_idle_state = 0; +#ifndef MODULE + static int did_version = 0; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); +#endif - dev = init_etherdev(dev, sizeof(struct speedo_private)); + dev = init_etherdev(NULL, sizeof(struct speedo_private)); if (dev->mem_start > 0) option = dev->mem_start; @@ -519,16 +701,31 @@ else option = 0; +#if defined(HAS_PCI_NETIF) + acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0); +#endif + /* Read the station address EEPROM before doing the reset. - Perhaps this should even be done before accepting the device, - then we wouldn't have a device name with which to report the error. */ + 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. + The size test is for 6 bit vs. 8 bit address serial EEPROMs. + */ { u16 sum = 0; int j; - int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6; + int read_cmd, ee_size; + + if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000) + == 0xffe0000) { + ee_size = 0x100; + read_cmd = EE_READ_CMD << 24; + } else { + ee_size = 0x40; + read_cmd = EE_READ_CMD << 22; + } - for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom(ioaddr, i, addr_len); + for (j = 0, i = 0; i < ee_size; i++) { + u16 value = do_eeprom_cmd(ioaddr, read_cmd | (i << 16), 27); eeprom[i] = value; sum += value; if (i < 3) { @@ -547,12 +744,12 @@ /* Reset the chip: stop Tx and Rx processes and clear counters. This takes less than 10usec and will easily finish before the next action. */ - outl(0, ioaddr + SCBPort); + outl(PortReset, ioaddr + SCBPort); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else - product = "Intel EtherExpress Pro 10/100"; + product = pci_tbl[chip_idx].name; printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr); @@ -560,7 +757,7 @@ printk("%2.2X:", dev->dev_addr[i]); printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq); -#ifndef kernel_bloat +#if 1 || defined(kernel_bloat) /* 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. */ @@ -605,7 +802,7 @@ self_test_results = (s32*) ((((long) str) + 15) & ~0xf); self_test_results[0] = 0; self_test_results[1] = -1; - outl(virt_to_bus(self_test_results) | 1, ioaddr + SCBPort); + outl(virt_to_bus(self_test_results) | PortSelfTest, ioaddr + SCBPort); do { udelay(10); } while (self_test_results[1] == -1 && --boguscnt >= 0); @@ -629,19 +826,33 @@ } #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 + /* We do a request_region() only to register /proc/ioports info. */ request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet"); dev->base_addr = ioaddr; dev->irq = irq; - if (dev->priv == NULL) - dev->priv = kmalloc(sizeof(*sp), GFP_KERNEL); sp = dev->priv; + if (dev->priv == NULL) { + void *mem = kmalloc(sizeof(*sp), GFP_KERNEL); + dev->priv = sp = mem; /* Cache align here if kmalloc does not. */ + sp->priv_addr = mem; + } memset(sp, 0, sizeof(*sp)); sp->next_module = root_speedo_dev; root_speedo_dev = dev; + sp->pci_bus = pci_bus; + sp->pci_devfn = pci_devfn; + sp->chip_id = chip_idx; + sp->acpi_pwr = acpi_idle_state; + sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { if (full_duplex[card_idx] >= 0) @@ -659,12 +870,16 @@ /* The Speedo-specific entries in the device structure. */ dev->open = &speedo_open; dev->hard_start_xmit = &speedo_start_xmit; +#if defined(HAS_NETIF_QUEUE) + dev->tx_timeout = &speedo_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; +#endif dev->stop = &speedo_close; dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; - return; + return dev; } /* Serial EEPROM section. @@ -673,47 +888,33 @@ #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ #define EE_CS 0x02 /* EEPROM chip select. */ #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ #define EE_ENB (0x4800 | EE_CS) +#define EE_WRITE_0 0x4802 +#define EE_WRITE_1 0x4806 +#define EE_OFFSET SCBeeprom /* Delay between EEPROM clock transitions. - This will actually work with no delay on 33Mhz PCI. */ -#define eeprom_delay(nanosec) udelay(1); - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << addr_len) -#define EE_READ_CMD (6 << addr_len) -#define EE_ERASE_CMD (7 << addr_len) + The code works with no delay on 33Mhz PCI. */ +#define eeprom_delay() inw(ee_addr) -static int read_eeprom(long ioaddr, int location, int addr_len) +static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len) { - unsigned short retval = 0; + unsigned retval = 0; long ee_addr = ioaddr + SCBeeprom; - int read_cmd = location | EE_READ_CMD; - int i; - - outw(EE_ENB & ~EE_CS, ee_addr); - outw(EE_ENB, ee_addr); - /* Shift the read command bits out. */ - for (i = 12; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outw(EE_ENB | dataval, ee_addr); - eeprom_delay(100); - outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(150); - } - outw(EE_ENB, ee_addr); + outw(EE_ENB | EE_SHIFT_CLK, ee_addr); - for (i = 15; i >= 0; i--) { - outw(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(100); + /* Shift the command bits out. */ + do { + short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + outw(dataval, ee_addr); + eeprom_delay(); + outw(dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); - outw(EE_ENB, ee_addr); - eeprom_delay(100); - } + } while (--cmd_len >= 0); + outw(EE_ENB, ee_addr); /* Terminate the EEPROM access. */ outw(EE_ENB & ~EE_CS, ee_addr); @@ -728,6 +929,7 @@ val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val); + break; } } while (! (val & 0x10000000)); return val & 0xffff; @@ -742,6 +944,7 @@ val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val); + break; } } while (! (val & 0x10000000)); return val & 0xffff; @@ -749,24 +952,34 @@ static int -speedo_open(struct device *dev) +speedo_open(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; -#ifdef notdef - /* We could reset the chip, but should not need to. */ - /* In fact we MUST NOT, unless we also re-do the init */ - outl(0, ioaddr + SCBPort); - udelay(10); +#if defined(HAS_PCI_NETIF) + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); #endif - /* This had better be initialized before we initialize the interrupt! */ - sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; - if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); + /* Set up the Tx queue early.. */ + sp->cur_tx = 0; + sp->dirty_tx = 0; + sp->last_cmd = 0; + sp->tx_full = 0; + sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + sp->in_interrupt = 0; + + /* .. we can safely take handler calls during init. */ + if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { + return -EAGAIN; + } + MOD_INC_USE_COUNT; + + dev->if_port = sp->default_port; + #ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us /* Retrigger negotiation to reset previous errors. */ if ((sp->phy[0] & 0x8000) == 0) { @@ -785,88 +998,30 @@ } #endif - /* Load the statistics block address. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer); - outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd); - sp->lstats.done_marker = 0; - speedo_init_rx_ring(dev); - wait_for_cmd_done(ioaddr + SCBCmd); - outl(0, ioaddr + SCBPointer); - outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd); - - /* Todo: verify that we must wait for previous command completion. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(sp->rx_ringp[0]), ioaddr + SCBPointer); - outw(INT_MASK | RX_START, ioaddr + SCBCmd); - - /* Fill the first command with our physical address. */ - { - u16 *eaddrs = (u16 *)dev->dev_addr; - u16 *setup_frm = (u16 *)&(sp->tx_ring[0].tx_desc_addr); - - /* Avoid a bug(?!) here by marking the command already completed. */ - sp->tx_ring[0].status = cpu_to_le32(((CmdSuspend | CmdIASetup) << 16) | 0xa000); - sp->tx_ring[0].link = cpu_to_le32(virt_to_bus(&(sp->tx_ring[1]))); - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; - } - sp->last_cmd = (struct descriptor *)&sp->tx_ring[0]; - sp->cur_tx = 1; - sp->dirty_tx = 0; - sp->tx_full = 0; - - wait_for_cmd_done(ioaddr + SCBCmd); - outl(0, ioaddr + SCBPointer); - outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd); - dev->if_port = sp->default_port; + /* Fire up the hardware. */ + outw(SCBMaskAll, ioaddr + SCBCmd); + speedo_resume(dev); - dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; - - /* - * Request the IRQ last, after we have set up all data structures. - * It would be bad to get an interrupt before we're ready. - * - * Register ourself first before turn on the interrupt. Someone - * else may share the same interrupt. H.J. - */ - if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, - "Intel EtherExpress Pro 10/100 Ethernet", dev)) { - return -EAGAIN; - } - - /* Start the chip's Tx process and unmask interrupts. */ - /* Todo: verify that we must wait for previous command completion. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(&sp->tx_ring[0]), ioaddr + SCBPointer); - outw(CU_START, ioaddr + SCBCmd); + netif_start_queue(dev); /* Setup the chip and configure the multicast list. */ - sp->mc_setup_frm = NULL; - sp->mc_setup_frm_len = 0; - sp->mc_setup_busy = 0; + sp->mc_setup_head = NULL; + sp->mc_setup_tail = NULL; + sp->flow_ctrl = sp->partner = 0; sp->rx_mode = -1; /* Invalid -> always reset the mode. */ set_rx_mode(dev); + if ((sp->phy[0] & 0x8000) == 0) + sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4); if (speedo_debug > 2) { printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n", dev->name, inw(ioaddr + SCBStatus)); } - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_DUMPSTATS, ioaddr + SCBCmd); - - /* No need to wait for the command unit to accept here. */ - if ((sp->phy[0] & 0x8000) == 0) - mdio_read(ioaddr, sp->phy[0] & 0x1f, 0); - - MOD_INC_USE_COUNT; - /* Set the timer. The timer serves a dual purpose: 1) to monitor the media interface (e.g. link beat) and perhaps switch to an alternate media type @@ -878,17 +1033,100 @@ sp->timer.function = &speedo_timer; /* timer handler */ add_timer(&sp->timer); + /* No need to wait for the command unit to accept here. */ + if ((sp->phy[0] & 0x8000) == 0) + mdio_read(ioaddr, sp->phy[0] & 0x1f, 0); + return 0; } +/* Start the chip hardware after a full reset. */ +static void speedo_resume(struct net_device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + + /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */ + sp->tx_threshold = 0x01208000; + + /* Set the segment registers to '0'. */ + wait_for_cmd_done(ioaddr + SCBCmd); + outl(0, ioaddr + SCBPointer); + outb(RxAddrLoad, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + outb(CUCmdBase, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + + /* Load the statistics block and rx ring addresses. */ + outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer); + outb(CUStatsAddr, ioaddr + SCBCmd); + sp->lstats.done_marker = 0; + wait_for_cmd_done(ioaddr + SCBCmd); + + if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n", + dev->name); + } else { + outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + } + + outb(CUDumpStats, ioaddr + SCBCmd); + + /* Fill the first command with our physical address. */ + { + struct descriptor *ias_cmd; + + ias_cmd = + (struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE]; + /* Avoid a bug(?!) here by marking the command already completed. */ + ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); + ias_cmd->link = + virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); + memcpy(ias_cmd->params, dev->dev_addr, 6); + sp->last_cmd = ias_cmd; + } + + /* Start the chip's Tx process and unmask interrupts. */ + wait_for_cmd_done(ioaddr + SCBCmd); + outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), + ioaddr + SCBPointer); + outw(CUStart, ioaddr + SCBCmd); +} + /* Media monitoring and control. */ static void speedo_timer(unsigned long data) { - struct device *dev = (struct device *)data; + struct net_device *dev = (struct net_device *)data; struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; + /* We have MII and lost link beat. */ + if ((sp->phy[0] & 0x8000) == 0) { + int partner = mdio_read(ioaddr, phy_num, 5); + if (partner != sp->partner) { + int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0; + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: Link status change.\n", dev->name); + sp->partner = partner; + if (flow_ctrl != sp->flow_ctrl) { + sp->flow_ctrl = flow_ctrl; + sp->rx_mode = -1; /* Trigger a reload. */ + } + /* Clear sticky bit. */ + mdio_read(ioaddr, phy_num, 1); + /* If link beat has returned... */ + if (mdio_read(ioaddr, phy_num, 1) & 0x0004) + dev->flags |= IFF_RUNNING; + else + dev->flags &= ~IFF_RUNNING; + } + } if (speedo_debug > 3) { - long ioaddr = dev->base_addr; printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); } @@ -897,6 +1135,9 @@ /* We haven't received a packet in a Long Time. We might have been bitten by the receiver hang bug. This can be cleared by sending a set multicast list command. */ + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: Sending a multicast list set command" + " from a timer routine.\n", dev->name); set_rx_mode(dev); } /* We must continue to monitor the media. */ @@ -904,9 +1145,48 @@ add_timer(&sp->timer); } +static void speedo_show_state(struct net_device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; + int i; + + /* Print a few items for debugging. */ + if (speedo_debug > 0) { + int i; + printk(KERN_DEBUG "%s: Tx ring dump, Tx queue %u / %u:\n", dev->name, + sp->cur_tx, sp->dirty_tx); + for (i = 0; i < TX_RING_SIZE; i++) + printk(KERN_DEBUG "%s: %c%c%2d %8.8x.\n", dev->name, + i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ', + i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ', + i, sp->tx_ring[i].status); + } + printk(KERN_DEBUG "%s: Printing Rx ring" + " (next to receive into %u, dirty index %u).\n", + dev->name, sp->cur_rx, sp->dirty_rx); + + for (i = 0; i < RX_RING_SIZE; i++) + printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name, + sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ', + i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ', + i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ', + i, (sp->rx_ringp[i] != NULL) ? + (unsigned)sp->rx_ringp[i]->status : 0); + + for (i = 0; i < 16; i++) { + /* FIXME: what does it mean? --SAW */ + if (i == 6) i = 21; + printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n", + dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i)); + } + +} + /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void -speedo_init_rx_ring(struct device *dev) +speedo_init_rx_ring(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; struct RxFD *rxf, *last_rxf = NULL; @@ -925,139 +1205,264 @@ sp->rx_ringp[i] = rxf; skb_reserve(skb, sizeof(struct RxFD)); if (last_rxf) - last_rxf->link = cpu_to_le32(virt_to_bus(rxf)); + last_rxf->link = virt_to_le32desc(rxf); last_rxf = rxf; - rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */ + rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */ rxf->link = 0; /* None yet. */ /* This field unused by i82557, we use it as a consistency check. */ #ifdef final_version rxf->rx_buf_addr = 0xffffffff; #else - rxf->rx_buf_addr = cpu_to_le32(virt_to_bus(skb->tail)); + rxf->rx_buf_addr = virt_to_bus(skb->tail); #endif - rxf->count = 0; - rxf->size = cpu_to_le16(PKT_BUF_SZ); + rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); } sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); /* Mark the last entry as end-of-list. */ - last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */ + last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */ sp->last_rxf = last_rxf; } -static void speedo_tx_timeout(struct device *dev) +static void speedo_purge_tx(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; + int entry; + + while ((int)(sp->cur_tx - sp->dirty_tx) > 0) { + entry = sp->dirty_tx % TX_RING_SIZE; + if (sp->tx_skbuff[entry]) { + sp->stats.tx_errors++; + dev_free_skb(sp->tx_skbuff[entry]); + sp->tx_skbuff[entry] = 0; + } + sp->dirty_tx++; + } + while (sp->mc_setup_head != NULL) { + struct speedo_mc_block *t; + if (speedo_debug > 1) + printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + sp->mc_setup_tail = NULL; + sp->tx_full = 0; + netif_wake_queue(dev); +} + +static void speedo_tx_timeout(struct net_device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; + int status = inw(ioaddr + SCBStatus); + unsigned long flags; printk(KERN_WARNING "%s: Transmit timed out: status %4.4x " " %4.4x at %d/%d command %8.8x.\n", - dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd), + dev->name, status, inw(ioaddr + SCBCmd), sp->dirty_tx, sp->cur_tx, - le32_to_cpu(sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status)); - if ((inw(ioaddr + SCBStatus) & 0x00C0) != 0x0080) { + sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status); + + /* Trigger a stats dump to give time before the reset. */ + speedo_get_stats(dev); + + speedo_show_state(dev); +#if 0 + if ((status & 0x00C0) != 0x0080 + && (status & 0x003C) == 0x0010) { + /* Only the command unit has stopped. */ printk(KERN_WARNING "%s: Trying to restart the transmitter...\n", dev->name); outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), ioaddr + SCBPointer); - outw(CU_START, ioaddr + SCBCmd); + outw(CUStart, ioaddr + SCBCmd); } else { - outw(DRVR_INT, ioaddr + SCBCmd); +#else + { +#endif + start_bh_atomic(); + /* Ensure that timer routine doesn't run! */ + del_timer(&sp->timer); + end_bh_atomic(); + /* Reset the Tx and Rx units. */ + outl(PortReset, ioaddr + SCBPort); + /* We may get spurious interrupts here. But I don't think that they + may do much harm. 1999/12/09 SAW */ + udelay(10); + /* Disable interrupts. */ + outw(SCBMaskAll, ioaddr + SCBCmd); + synchronize_irq(); + speedo_tx_buffer_gc(dev); + /* Free as much as possible. + It helps to recover from a hang because of out-of-memory. + It also simplifies speedo_resume() in case TX ring is full or + close-to-be full. */ + speedo_purge_tx(dev); + speedo_refill_rx_buffers(dev, 1); + spin_lock_irqsave(&sp->lock, flags); + speedo_resume(dev); + sp->rx_mode = -1; + dev->trans_start = jiffies; + spin_unlock_irqrestore(&sp->lock, flags); + set_rx_mode(dev); /* it takes the spinlock itself --SAW */ + sp->timer.expires = RUN_AT(2*HZ); + add_timer(&sp->timer); } -#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f; + int advertising = mdio_read(ioaddr, phy_addr, 4); + int mii_bmcr = mdio_read(ioaddr, phy_addr, 0); mdio_write(ioaddr, phy_addr, 0, 0x0400); mdio_write(ioaddr, phy_addr, 1, 0x0000); mdio_write(ioaddr, phy_addr, 4, 0x0000); mdio_write(ioaddr, phy_addr, 0, 0x8000); #ifdef honor_default_port mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]); +#else + mdio_read(ioaddr, phy_addr, 0); + mdio_write(ioaddr, phy_addr, 0, mii_bmcr); + mdio_write(ioaddr, phy_addr, 4, advertising); #endif } -#endif - sp->stats.tx_errors++; - dev->trans_start = jiffies; return; } static int -speedo_start_xmit(struct sk_buff *skb, struct device *dev) +speedo_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; int entry; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - If this ever occurs the queue layer is doing something evil! */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { +#if ! defined(HAS_NETIF_QUEUE) + if (test_bit(0, (void*)&dev->tbusy) != 0) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < TX_TIMEOUT - 2) return 1; if (tickssofar < TX_TIMEOUT) { /* Reap sent packets from the full Tx queue. */ - outw(DRVR_INT, ioaddr + SCBCmd); + outw(SCBTriggerIntr, ioaddr + SCBCmd); return 1; } speedo_tx_timeout(dev); return 1; } - - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ +#endif { /* Prevent interrupts from changing the Tx ring from underneath us. */ unsigned long flags; spin_lock_irqsave(&sp->lock, flags); + /* Check if there are enough space. */ + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name); + netif_stop_queue(dev); + sp->tx_full = 1; + spin_unlock_irqrestore(&sp->lock, flags); + return 1; + } + /* Calculate the Tx descriptor entry. */ entry = sp->cur_tx++ % TX_RING_SIZE; sp->tx_skbuff[entry] = skb; - /* Todo: be a little more clever about setting the interrupt bit. */ sp->tx_ring[entry].status = - cpu_to_le32((CmdSuspend | CmdTx | CmdTxFlex) << 16); + cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); + if (!(entry & ((TX_RING_SIZE>>2)-1))) + sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr); sp->tx_ring[entry].link = - cpu_to_le32(virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE])); + virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); sp->tx_ring[entry].tx_desc_addr = - cpu_to_le32(virt_to_bus(&sp->tx_ring[entry].tx_buf_addr0)); - /* The data region is always in one buffer descriptor, Tx FIFO - threshold of 256. */ - sp->tx_ring[entry].count = cpu_to_le32(0x01208000); - sp->tx_ring[entry].tx_buf_addr0 = cpu_to_le32(virt_to_bus(skb->data)); + virt_to_le32desc(&sp->tx_ring[entry].tx_buf_addr0); + /* The data region is always in one buffer descriptor. */ + sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); + sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32desc(skb->data); sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); - /* Todo: perhaps leave the interrupt bit set if the Tx queue is more - than half full. Argument against: we should be receiving packets - and scavenging the queue. Argument for: if so, it shouldn't - matter. */ - sp->last_cmd->command &= cpu_to_le16(~(CmdSuspend | CmdIntr)); - sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; - /* Trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); + clear_suspend(sp->last_cmd); + /* We want the time window between clearing suspend flag on the previous + command and resuming CU to be as small as possible. + Interrupts in between are very undesired. --SAW */ + outb(CUResume, ioaddr + SCBCmd); + sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; + /* Leave room for set_rx_mode(). If there is no more space than reserved + for multicast filter mark the ring as full. */ + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } + spin_unlock_irqrestore(&sp->lock, flags); } - /* Leave room for set_rx_mode() to fill two entries. */ - if (sp->cur_tx - sp->dirty_tx > TX_RING_SIZE - 3) - sp->tx_full = 1; - else - clear_bit(0, (void*)&dev->tbusy); - dev->trans_start = jiffies; return 0; } +static void speedo_tx_buffer_gc(struct net_device *dev) +{ + unsigned int dirty_tx; + struct speedo_private *sp = (struct speedo_private *)dev->priv; + + dirty_tx = sp->dirty_tx; + while ((int)(sp->cur_tx - dirty_tx) > 0) { + int entry = dirty_tx % TX_RING_SIZE; + int status = le32_to_cpu(sp->tx_ring[entry].status); + + if (speedo_debug > 5) + printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n", + entry, status); + if ((status & StatusComplete) == 0) + break; /* It still hasn't been processed. */ + if (status & TxUnderrun) + if (sp->tx_threshold < 0x01e08000) { + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n", + dev->name); + sp->tx_threshold += 0x00040000; + } + /* Free the original skb. */ + if (sp->tx_skbuff[entry]) { + sp->stats.tx_packets++; /* Count only user packets. */ + sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; + dev_free_skb(sp->tx_skbuff[entry]); + sp->tx_skbuff[entry] = 0; + } + dirty_tx++; + } + + if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { + printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," + " full=%d.\n", + dirty_tx, sp->cur_tx, sp->tx_full); + dirty_tx += TX_RING_SIZE; + } + + while (sp->mc_setup_head != NULL + && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { + struct speedo_mc_block *t; + if (speedo_debug > 1) + printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + if (sp->mc_setup_head == NULL) + sp->mc_setup_tail = NULL; + + sp->dirty_tx = dirty_tx; +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { - struct device *dev = (struct device *)dev_instance; + struct net_device *dev = (struct net_device *)dev_instance; struct speedo_private *sp; long ioaddr, boguscnt = max_interrupt_work; unsigned short status; @@ -1071,9 +1476,15 @@ ioaddr = dev->base_addr; sp = (struct speedo_private *)dev->priv; - spin_lock(&sp->lock); #ifndef final_version + /* A lock to prevent simultaneous entry on SMP machines. */ + if (test_and_set_bit(0, (void*)&sp->in_interrupt)) { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + sp->in_interrupt = 0; /* Avoid halting machine. */ + return; + } dev->interrupt = 1; #endif @@ -1088,64 +1499,91 @@ if ((status & 0xfc00) == 0) break; + + /* Always check if all rx buffers are allocated. --SAW */ + speedo_refill_rx_buffers(dev, 0); - if (status & 0x4000) /* Packet received. */ + if ((status & 0x5000) || /* Packet received, or Rx error. */ + (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) + /* Need to gather the postponed packet. */ speedo_rx(dev); if (status & 0x1000) { - if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */ - outw(RX_RESUMENR, ioaddr + SCBCmd); - else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */ - /* No idea of what went wrong. Restart the receiver. */ + spin_lock(&sp->lock); + if ((status & 0x003c) == 0x0028) { /* No more Rx buffers. */ + struct RxFD *rxf; + printk(KERN_WARNING "%s: card reports no RX buffers.\n", + dev->name); + rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]; + if (rxf == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: NULL cur_rx in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else if (rxf == sp->last_rxf) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: cur_rx is last in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else + outb(RxResumeNoResources, ioaddr + SCBCmd); + } else if ((status & 0x003c) == 0x0008) { /* No resources. */ + struct RxFD *rxf; + printk(KERN_WARNING "%s: card reports no resources.\n", + dev->name); + rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]; + if (rxf == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: NULL cur_rx in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else if (rxf == sp->last_rxf) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: cur_rx is last in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else { + /* Restart the receiver. */ + outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + } + } + sp->stats.rx_errors++; + spin_unlock(&sp->lock); + } + + if ((sp->rx_ring_state&(RrNoMem|RrNoResources)) == RrNoResources) { + printk(KERN_WARNING + "%s: restart the receiver after a possible hang.\n", + dev->name); + spin_lock(&sp->lock); + /* Restart the receiver. + I'm not sure if it's always right to restart the receiver + here but I don't know another way to prevent receiver hangs. + 1999/12/25 SAW */ outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), - ioaddr + SCBPointer); - outw(RX_START, ioaddr + SCBCmd); - } - sp->stats.rx_errors++; + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + sp->rx_ring_state &= ~RrNoResources; + spin_unlock(&sp->lock); } /* User interrupt, Command/Tx unit interrupt or CU not active. */ if (status & 0xA400) { - unsigned int dirty_tx = sp->dirty_tx; - - while (sp->cur_tx - dirty_tx > 0) { - int entry = dirty_tx % TX_RING_SIZE; - int status = le32_to_cpu(sp->tx_ring[entry].status); - - if (speedo_debug > 5) - printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n", - entry, status); - if ((status & StatusComplete) == 0) - break; /* It still hasn't been processed. */ - /* Free the original skb. */ - if (sp->tx_skbuff[entry]) { - sp->stats.tx_packets++; /* Count only user packets. */ - sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */ - dev_free_skb(sp->tx_skbuff[entry]); - sp->tx_skbuff[entry] = 0; - } else if ((status&0x70000) == CmdNOp << 16) - sp->mc_setup_busy = 0; - dirty_tx++; - } - -#ifndef final_version - if (sp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," - " full=%d.\n", - dirty_tx, sp->cur_tx, sp->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - - if (sp->tx_full && dev->tbusy - && dirty_tx > sp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ + spin_lock(&sp->lock); + speedo_tx_buffer_gc(dev); + if (sp->tx_full + && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { + /* The ring is no longer full. */ sp->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ } - - sp->dirty_tx = dirty_tx; + spin_unlock(&sp->lock); } if (--boguscnt < 0) { @@ -1162,34 +1600,131 @@ dev->name, inw(ioaddr + SCBStatus)); dev->interrupt = 0; - spin_unlock(&sp->lock); + clear_bit(0, (void*)&sp->in_interrupt); return; } +static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + struct RxFD *rxf; + struct sk_buff *skb; + /* Get a fresh skbuff to replace the consumed one. */ + skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); + sp->rx_skbuff[entry] = skb; + if (skb == NULL) { + sp->rx_ringp[entry] = NULL; + return NULL; + } + rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; + skb->dev = dev; + skb_reserve(skb, sizeof(struct RxFD)); + rxf->rx_buf_addr = virt_to_bus(skb->tail); + return rxf; +} + +static inline void speedo_rx_link(struct net_device *dev, int entry, + struct RxFD *rxf) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */ + rxf->link = 0; /* None yet. */ + rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); + sp->last_rxf->link = virt_to_le32desc(rxf); + sp->last_rxf->status &= cpu_to_le32(~0xC0000000); + sp->last_rxf = rxf; +} + +static int speedo_refill_rx_buf(struct net_device *dev, int force) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + int entry; + struct RxFD *rxf; + + entry = sp->dirty_rx % RX_RING_SIZE; + if (sp->rx_skbuff[entry] == NULL) { + rxf = speedo_rx_alloc(dev, entry); + if (rxf == NULL) { + unsigned int forw; + int forw_entry; + if (speedo_debug > 2 || !(sp->rx_ring_state & RrOOMReported)) { + printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n", + dev->name, force); + speedo_show_state(dev); + sp->rx_ring_state |= RrOOMReported; + } + if (!force) + return -1; /* Better luck next time! */ + /* Borrow an skb from one of next entries. */ + for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++) + if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL) + break; + if (forw == sp->cur_rx) + return -1; + forw_entry = forw % RX_RING_SIZE; + sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry]; + sp->rx_skbuff[forw_entry] = NULL; + rxf = sp->rx_ringp[forw_entry]; + sp->rx_ringp[forw_entry] = NULL; + sp->rx_ringp[entry] = rxf; + } + } else { + rxf = sp->rx_ringp[entry]; + } + speedo_rx_link(dev, entry, rxf); + sp->dirty_rx++; + sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */ + return 0; +} + +static void speedo_refill_rx_buffers(struct net_device *dev, int force) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + + /* Refill the RX ring. */ + while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && + speedo_refill_rx_buf(dev, force) != -1); +} + static int -speedo_rx(struct device *dev) +speedo_rx(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; int entry = sp->cur_rx % RX_RING_SIZE; int status; int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; + int alloc_ok = 1; if (speedo_debug > 4) printk(KERN_DEBUG " In speedo_rx().\n"); /* If we own the next entry, it's a new packet. Send it up. */ while (sp->rx_ringp[entry] != NULL && (status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete) { + int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; if (--rx_work_limit < 0) break; + + /* Check for a rare out-of-memory case: the current buffer is + the last buffer allocated in the RX ring. --SAW */ + if (sp->last_rxf == sp->rx_ringp[entry]) { + /* Postpone the packet. It'll be reaped at an interrupt when this + packet is no longer the last packet in the ring. */ + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: RX packet postponed!\n", + dev->name); + sp->rx_ring_state |= RrPostponed; + break; + } + if (speedo_debug > 4) printk(KERN_DEBUG " speedo_rx() status %8.8x len %d.\n", status, - le16_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff); - if ((status & (RxErrTooBig|RxOK)) != RxOK) { + pkt_len); + if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { if (status & RxErrTooBig) printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, " "status %8.8x!\n", dev->name, status); - else if ( ! (status & 0x2000)) { + else if (! (status & RxOK)) { /* There was a fatal error. This *should* be impossible. */ sp->stats.rx_errors++; printk(KERN_ERR "%s: Anomalous event in speedo_rx(), " @@ -1197,7 +1732,6 @@ dev->name, status); } } else { - int pkt_len = le16_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; struct sk_buff *skb; /* Check if the packet is long enough to just accept without @@ -1209,13 +1743,11 @@ /* 'skb_put()' points to the start of sk_buff data area. */ #if !defined(__alpha__) /* Packet is in one chunk -- we can copy + cksum. */ - eth_copy_and_sum(skb, - bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)), - pkt_len, 0); + eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), - bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)), pkt_len); + memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail, + pkt_len); #endif } else { void *temp; @@ -1228,64 +1760,44 @@ } sp->rx_skbuff[entry] = NULL; temp = skb_put(skb, pkt_len); - if (bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)) != temp) + if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp) printk(KERN_ERR "%s: Rx consistency error -- the skbuff " "addresses do not match in speedo_rx: %p vs. %p " "/ %p.\n", dev->name, - bus_to_virt(le32_to_cpu(sp->rx_ringp[entry]->rx_buf_addr)), + bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), skb->head, temp); sp->rx_ringp[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); sp->stats.rx_packets++; - sp->stats.rx_bytes += pkt_len; /* Count received bytes */ + sp->stats.rx_bytes += pkt_len; } entry = (++sp->cur_rx) % RX_RING_SIZE; + sp->rx_ring_state &= ~RrPostponed; + /* Refill the recently taken buffers. + Do it one-by-one to handle traffic bursts better. */ + if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1) + alloc_ok = 0; } - /* Refill the Rx ring buffers. */ - for (; sp->dirty_rx < sp->cur_rx; sp->dirty_rx++) { - struct RxFD *rxf; - entry = sp->dirty_rx % RX_RING_SIZE; - if (sp->rx_skbuff[entry] == NULL) { - struct sk_buff *skb; - /* Get a fresh skbuff to replace the consumed one. */ - skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); - sp->rx_skbuff[entry] = skb; - if (skb == NULL) { - sp->rx_ringp[entry] = NULL; - break; /* Better luck next time! */ - } - rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; - skb->dev = dev; - skb_reserve(skb, sizeof(struct RxFD)); - rxf->rx_buf_addr = cpu_to_le32(virt_to_bus(skb->tail)); - } else { - rxf = sp->rx_ringp[entry]; - } - rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */ - rxf->link = 0; /* None yet. */ - rxf->count = 0; - rxf->size = cpu_to_le16(PKT_BUF_SZ); - sp->last_rxf->link = cpu_to_le32(virt_to_bus(rxf)); - sp->last_rxf->status &= cpu_to_le32(~0xC0000000); - sp->last_rxf = rxf; - } + /* Try hard to refill the recently taken buffers. */ + speedo_refill_rx_buffers(dev, 1); sp->last_rx_time = jiffies; + return 0; } static int -speedo_close(struct device *dev) +speedo_close(struct net_device *dev) { long ioaddr = dev->base_addr; struct speedo_private *sp = (struct speedo_private *)dev->priv; int i; dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); if (speedo_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n", @@ -1294,13 +1806,16 @@ /* Shut off the media monitoring timer. */ del_timer(&sp->timer); - /* Disable interrupts, and stop the chip's Rx process. */ - outw(INT_MASK, ioaddr + SCBCmd); - outw(INT_MASK | RX_ABORT, ioaddr + SCBCmd); + /* Shutting down the chip nicely fails to disable flow control. So.. */ + outl(PortPartialReset, ioaddr + SCBPort); free_irq(dev->irq, dev); + + /* Print a few items for debugging. */ + if (speedo_debug > 3) + speedo_show_state(dev); - /* Free all the skbuffs in the Rx and Tx queues. */ + /* Free all the skbuffs in the Rx and Tx queues. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = sp->rx_skbuff[i]; sp->rx_skbuff[i] = 0; @@ -1316,28 +1831,22 @@ if (skb) dev_free_skb(skb); } - if (sp->mc_setup_frm) { - kfree(sp->mc_setup_frm); - sp->mc_setup_frm_len = 0; - } - /* Print a few items for debugging. */ - if (speedo_debug > 3) { - int phy_num = sp->phy[0] & 0x1f; - printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n", - dev->name, sp->cur_rx); - - for (i = 0; i < RX_RING_SIZE; i++) - printk(KERN_DEBUG " Rx ring entry %d %8.8x.\n", - i, (int)le32_to_cpu(sp->rx_ringp[i]->status)); - - for (i = 0; i < 5; i++) - printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", - phy_num, i, mdio_read(ioaddr, phy_num, i)); - for (i = 21; i < 26; i++) - printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", - phy_num, i, mdio_read(ioaddr, phy_num, i)); - } + /* Free multicast setting blocks. */ + for (i = 0; sp->mc_setup_head != NULL; i++) { + struct speedo_mc_block *t; + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + sp->mc_setup_tail = NULL; + if (speedo_debug > 0) + printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i); + +#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 MOD_DEC_USE_COUNT; return 0; @@ -1356,12 +1865,13 @@ Oh, and incoming frames are dropped while executing dump-stats! */ static struct enet_statistics * -speedo_get_stats(struct device *dev) +speedo_get_stats(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; - if (le32_to_cpu(sp->lstats.done_marker) == 0xA007) { /* Previous dump finished */ + /* Update only if the previous dump finished. */ + if (sp->lstats.done_marker == le32_to_cpu(0xA007)) { sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats.tx_coll16_errs); sp->stats.tx_window_errors += le32_to_cpu(sp->lstats.tx_late_colls); sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_underruns); @@ -1375,30 +1885,50 @@ sp->stats.rx_length_errors += le32_to_cpu(sp->lstats.rx_runt_errs); sp->lstats.done_marker = 0x0000; if (dev->start) { + unsigned long flags; + /* Take a spinlock to make wait_for_cmd_done and sending the + * command atomic. --SAW */ + spin_lock_irqsave(&sp->lock, flags); wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_DUMPSTATS, ioaddr + SCBCmd); + outb(CUDumpStats, ioaddr + SCBCmd); + spin_unlock_irqrestore(&sp->lock, flags); } } return &sp->stats; } -static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd) +static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct speedo_private *sp = (struct speedo_private *)dev->priv; 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 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); + 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 return 0; default: return -EOPNOTSUPP; @@ -1414,8 +1944,7 @@ loaded the link -- we convert the current command block, normally a Tx command, into a no-op and link it to the new command. */ -static void -set_rx_mode(struct device *dev) +static void set_rx_mode(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; @@ -1431,10 +1960,14 @@ new_rx_mode = 1; } else new_rx_mode = 0; + + if (speedo_debug > 3) + printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name, + sp->rx_mode, new_rx_mode); - if (sp->cur_tx - sp->dirty_tx >= TX_RING_SIZE - 1) { - /* The Tx ring is full -- don't add anything! Presumably the new mode - is in config_cmd_data and will be added anyway. */ + if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) { + /* The Tx ring is full -- don't add anything! Hope the mode will be + * set again later. */ sp->rx_mode = -1; return; } @@ -1448,9 +1981,9 @@ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; sp->tx_skbuff[entry] = 0; /* Redundant. */ - sp->tx_ring[entry].status = cpu_to_le32((CmdSuspend | CmdConfigure) << 16); + sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure); sp->tx_ring[entry].link = - cpu_to_le32(virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE])); + virt_to_le32desc(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr; /* Construct a full CmdConfig frame. */ memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -1458,6 +1991,7 @@ config_cmd_data[4] = rxdmacount; config_cmd_data[5] = txdmacount + 0x80; config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0; + config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80; config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0; config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05; if (sp->phy[0] & 0x8000) { /* Use the AUI port instead. */ @@ -1465,11 +1999,13 @@ config_cmd_data[8] = 0; } /* Trigger the command unit resume. */ - last_cmd->command &= cpu_to_le16(~CmdSuspend); - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); - + clear_suspend(last_cmd); + outb(CUResume, ioaddr + SCBCmd); + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); } @@ -1485,9 +2021,9 @@ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; sp->tx_skbuff[entry] = 0; - sp->tx_ring[entry].status = cpu_to_le32((CmdSuspend | CmdMulticastList) << 16); + sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList); sp->tx_ring[entry].link = - cpu_to_le32(virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE])); + virt_to_le32desc(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */ setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr; *setup_params++ = cpu_to_le16(dev->mc_count*6); @@ -1500,48 +2036,40 @@ *setup_params++ = *eaddrs++; } - last_cmd->command &= cpu_to_le16(~CmdSuspend); - - /* Immediately trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); + clear_suspend(last_cmd); + /* Immediately trigger the command unit resume. */ + outb(CUResume, ioaddr + SCBCmd); + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); } else if (new_rx_mode == 0) { struct dev_mc_list *mclist; u16 *setup_params, *eaddrs; - struct descriptor *mc_setup_frm = sp->mc_setup_frm; + struct speedo_mc_block *mc_blk; + struct descriptor *mc_setup_frm; int i; - if (sp->mc_setup_frm_len < 10 + dev->mc_count*6 - || sp->mc_setup_frm == NULL) { - /* Allocate a full setup frame, 10bytes + . */ - if (sp->mc_setup_frm) - kfree(sp->mc_setup_frm); - sp->mc_setup_busy = 0; - sp->mc_setup_frm_len = 10 + multicast_filter_limit*6; - sp->mc_setup_frm = kmalloc(sp->mc_setup_frm_len, GFP_ATOMIC); - if (sp->mc_setup_frm == NULL) { - printk(KERN_ERR "%s: Failed to allocate a setup frame.\n", - dev->name); - sp->rx_mode = -1; /* We failed, try again. */ - return; - } - } - /* If we are busy, someone might be quickly adding to the MC list. - Try again later when the list changes stop. */ - if (sp->mc_setup_busy) { - sp->rx_mode = -1; + mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6, + GFP_ATOMIC); + if (mc_blk == NULL) { + printk(KERN_ERR "%s: Failed to allocate a setup frame.\n", + dev->name); + sp->rx_mode = -1; /* We failed, try again. */ return; } - mc_setup_frm = sp->mc_setup_frm; + mc_blk->next = NULL; + mc_setup_frm = &mc_blk->frame; + /* Fill the setup frame. */ if (speedo_debug > 1) - printk(KERN_DEBUG "%s: Constructing a setup frame at %p, " - "%d bytes.\n", - dev->name, sp->mc_setup_frm, sp->mc_setup_frm_len); - mc_setup_frm->status = 0; - mc_setup_frm->command = cpu_to_le16(CmdSuspend | CmdIntr | CmdMulticastList); + printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n", + dev->name, mc_setup_frm); + mc_setup_frm->cmd_status = + cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList); /* Link set below. */ setup_params = (u16 *)&mc_setup_frm->params; *setup_params++ = cpu_to_le16(dev->mc_count*6); @@ -1557,26 +2085,35 @@ /* Disable interrupts while playing with the Tx Cmd list. */ spin_lock_irqsave(&sp->lock, flags); + if (sp->mc_setup_tail) + sp->mc_setup_tail->next = mc_blk; + else + sp->mc_setup_head = mc_blk; + sp->mc_setup_tail = mc_blk; + mc_blk->tx = sp->cur_tx; + entry = sp->cur_tx++ % TX_RING_SIZE; last_cmd = sp->last_cmd; sp->last_cmd = mc_setup_frm; - sp->mc_setup_busy++; /* Change the command to a NoOp, pointing to the CmdMulti command. */ sp->tx_skbuff[entry] = 0; - sp->tx_ring[entry].status = cpu_to_le32(CmdNOp << 16); - sp->tx_ring[entry].link = cpu_to_le32(virt_to_bus(mc_setup_frm)); + sp->tx_ring[entry].status = cpu_to_le32(CmdNOp); + sp->tx_ring[entry].link = virt_to_le32desc(mc_setup_frm); /* Set the link in the setup frame. */ mc_setup_frm->link = - cpu_to_le32(virt_to_bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]))); - - last_cmd->command &= cpu_to_le16(~CmdSuspend); + virt_to_le32desc(&(sp->tx_ring[(entry+1) % TX_RING_SIZE])); - /* Immediately trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); + clear_suspend(last_cmd); + /* Immediately trigger the command unit resume. */ + outb(CUResume, ioaddr + SCBCmd); + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); if (speedo_debug > 5) @@ -1589,41 +2126,65 @@ #ifdef MODULE -int -init_module(void) +int init_module(void) { int cards_found; + if (debug >= 0 && speedo_debug != debug) + printk(KERN_INFO "eepro100.c: Debug level is %d.\n", debug); if (debug >= 0) speedo_debug = debug; + /* Always emit the version message. */ if (speedo_debug) printk(KERN_INFO "%s", version); - root_speedo_dev = NULL; - cards_found = eepro100_init(NULL); - return cards_found ? 0 : -ENODEV; +#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; } void cleanup_module(void) { - struct device *next_dev; + struct net_device *next_dev; /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_speedo_dev) { - next_dev = ((struct speedo_private *)root_speedo_dev->priv)->next_module; + struct speedo_private *sp = (void *)root_speedo_dev->priv; unregister_netdev(root_speedo_dev); +#ifdef USE_IO release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE); +#else + 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 + next_dev = sp->next_module; + if (sp->priv_addr) + kfree(sp->priv_addr); kfree(root_speedo_dev); root_speedo_dev = next_dev; } } + #else /* not MODULE */ -int eepro100_probe(struct device *dev) + +int eepro100_probe(void) { int cards_found = 0; - cards_found = eepro100_init(dev); + cards_found = eepro100_init(); if (speedo_debug > 0 && cards_found) printk(version); Index: oldkernel/linux/include/linux/pci.h diff -u linux/include/linux/pci.h:1.3 linux/include/linux/pci.h:1.4 --- linux/include/linux/pci.h:1.3 Thu Jun 1 14:11:18 2000 +++ linux/include/linux/pci.h Thu Jun 1 16:52:50 2000 @@ -1088,6 +1088,7 @@ #define PCI_DEVICE_ID_INTEL_82430 0x0486 #define PCI_DEVICE_ID_INTEL_82434 0x04a3 #define PCI_DEVICE_ID_INTEL_I960 0x0960 +#define PCI_DEVICE_ID_INTEL_82559ER 0x1209 #define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 #define PCI_DEVICE_ID_INTEL_82092AA_1 0x1222 #define PCI_DEVICE_ID_INTEL_7116 0x1223