X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fpcnet32.c;h=076f23a10517f45938e6a5764c5178d5189b61df;hb=91e2ff3528ac90b9dbcb04b76488e8ad74e3d3d9;hp=8613610186407f37454fb8c2a9284e8fbf667d0e;hpb=4a5e8e296cfdeef18312c08199f25c00ec148f41;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 8613610..076f23a 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.32" -#define DRV_RELDATE "18.Mar.2006" +#define DRV_VERSION "1.35" +#define DRV_RELDATE "21.Apr.2008" #define PFX DRV_NAME ": " static const char *const version = @@ -31,6 +31,7 @@ static const char *const version = #include #include +#include #include #include #include @@ -58,18 +59,15 @@ static const char *const version = * PCI device identifiers for "new style" Linux PCI Device Drivers */ static struct pci_device_id pcnet32_pci_tbl[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), }, /* * Adapters that were sold with IBM's RS/6000 or pSeries hardware have * the incorrect vendor id. */ - { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, - PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0}, + { PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE), + .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, }, { } /* terminate list */ }; @@ -136,7 +134,7 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { "Loopback test (offline)" }; -#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) +#define PCNET32_TEST_LEN ARRAY_SIZE(pcnet32_gstrings_test) #define PCNET32_NUM_REGS 136 @@ -156,126 +154,6 @@ static int homepna[MAX_UNITS]; */ /* - * History: - * v0.01: Initial version - * only tested on Alpha Noname Board - * v0.02: changed IRQ handling for new interrupt scheme (dev_id) - * tested on a ASUS SP3G - * v0.10: fixed an odd problem with the 79C974 in a Compaq Deskpro XL - * looks like the 974 doesn't like stopping and restarting in a - * short period of time; now we do a reinit of the lance; the - * bug was triggered by doing ifconfig eth0 broadcast - * and hangs the machine (thanks to Klaus Liedl for debugging) - * v0.12: by suggestion from Donald Becker: Renamed driver to pcnet32, - * made it standalone (no need for lance.c) - * v0.13: added additional PCI detecting for special PCI devices (Compaq) - * v0.14: stripped down additional PCI probe (thanks to David C Niemi - * and sveneric@xs4all.nl for testing this on their Compaq boxes) - * v0.15: added 79C965 (VLB) probe - * added interrupt sharing for PCI chips - * v0.16: fixed set_multicast_list on Alpha machines - * v0.17: removed hack from dev.c; now pcnet32 uses ethif_probe in Space.c - * v0.19: changed setting of autoselect bit - * v0.20: removed additional Compaq PCI probe; there is now a working one - * in arch/i386/bios32.c - * v0.21: added endian conversion for ppc, from work by cort@cs.nmt.edu - * v0.22: added printing of status to ring dump - * v0.23: changed enet_statistics to net_devive_stats - * v0.90: added multicast filter - * added module support - * changed irq probe to new style - * added PCnetFast chip id - * added fix for receive stalls with Intel saturn chipsets - * added in-place rx skbs like in the tulip driver - * minor cleanups - * v0.91: added PCnetFast+ chip id - * back port to 2.0.x - * v1.00: added some stuff from Donald Becker's 2.0.34 version - * added support for byte counters in net_dev_stats - * v1.01: do ring dumps, only when debugging the driver - * increased the transmit timeout - * v1.02: fixed memory leak in pcnet32_init_ring() - * v1.10: workaround for stopped transmitter - * added port selection for modules - * detect special T1/E1 WAN card and setup port selection - * v1.11: fixed wrong checking of Tx errors - * v1.20: added check of return value kmalloc (cpeterso@cs.washington.edu) - * added save original kmalloc addr for freeing (mcr@solidum.com) - * added support for PCnetHome chip (joe@MIT.EDU) - * rewritten PCI card detection - * added dwio mode to get driver working on some PPC machines - * v1.21: added mii selection and mii ioctl - * v1.22: changed pci scanning code to make PPC people happy - * fixed switching to 32bit mode in pcnet32_open() (thanks - * to Michael Richard for noticing this one) - * added sub vendor/device id matching (thanks again to - * Michael Richard ) - * added chip id for 79c973/975 (thanks to Zach Brown ) - * v1.23 fixed small bug, when manual selecting MII speed/duplex - * v1.24 Applied Thomas' patch to use TxStartPoint and thus decrease TxFIFO - * underflows. Added tx_start_pt module parameter. Increased - * TX_RING_SIZE from 16 to 32. Added #ifdef'd code to use DXSUFLO - * for FAST[+] chipsets. - * v1.24ac Added SMP spinlocking - Alan Cox - * v1.25kf Added No Interrupt on successful Tx for some Tx's - * v1.26 Converted to pci_alloc_consistent, Jamey Hicks / George France - * - * - Fixed a few bugs, related to running the controller in 32bit mode. - * 23 Oct, 2000. Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * v1.26p Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker - * v1.27 improved CSR/PROM address detection, lots of cleanups, - * new pcnet32vlb module option, HP-PARISC support, - * added module parameter descriptions, - * initial ethtool support - Helge Deller - * v1.27a Sun Feb 10 2002 Go Taniguchi - * use alloc_etherdev and register_netdev - * fix pci probe not increment cards_found - * FD auto negotiate error workaround for xSeries250 - * clean up and using new mii module - * v1.27b Sep 30 2002 Kent Yoder - * Added timer for cable connection state changes. - * v1.28 20 Feb 2004 Don Fry - * Jon Mason , Chinmay Albal - * Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl. - * Fixes bogus 'Bus master arbitration failure', pci_[un]map_single - * length errors, and transmit hangs. Cleans up after errors in open. - * Jim Lewis added ethernet loopback test. - * Thomas Munck Steenholdt non-mii ioctl corrections. - * v1.29 6 Apr 2004 Jim Lewis added physical - * identification code (blink led's) and register dump. - * Don Fry added timer for 971/972 so skbufs don't remain on tx ring - * forever. - * v1.30 18 May 2004 Don Fry removed timer and Last Transmit Interrupt - * (ltint) as they added complexity and didn't give good throughput. - * v1.30a 22 May 2004 Don Fry limit frames received during interrupt. - * v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973, - * assisted by Bruce Penrod . - * v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart. - * v1.30d 01 Jun 2004 Don Fry discard oversize rx packets. - * v1.30e 11 Jun 2004 Don Fry recover after fifo error and rx hang. - * v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI, - * expanding on suggestions from Ralf Baechle , - * and Brian Murphy . - * v1.30g 22 Jun 2004 Patrick Simmons added option - * homepna for selecting HomePNA mode for PCNet/Home 79C978. - * v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32. - * v1.30i 28 Jun 2004 Don Fry change to use module_param. - * v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test. - * v1.31 02 Sep 2005 Hubert WS Lin added set_ringparam(). - * v1.31a 12 Sep 2005 Hubert WS Lin set min ring size to 4 - * to allow loopback test to work unchanged. - * v1.31b 06 Oct 2005 Don Fry changed alloc_ring to show name of device - * if allocation fails - * v1.31c 01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only. - * Force 100Mbit FD if Auto (ASEL) is selected. - * See Bugzilla 2669 and 4551. - * v1.32 18 Mar2006 Thomas Bogendoerfer and Don Fry added Multi-Phy - * handling for supporting AT-270x FTX cards with FX and Tx PHYs. - * Philippe Seewer assisted with auto negotiation and testing. - */ - -/* * Set the number of Tx and Rx buffers, using Log_2(# buffers). * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). @@ -293,7 +171,11 @@ static int homepna[MAX_UNITS]; #define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS)) #define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS)) -#define PKT_BUF_SZ 1544 +#define PKT_BUF_SKB 1544 +/* actual buffer length after being aligned */ +#define PKT_BUF_SIZE (PKT_BUF_SKB - NET_IP_ALIGN) +/* chip wants twos complement of the (aligned) buffer length */ +#define NEG_BUF_SIZE (NET_IP_ALIGN - PKT_BUF_SKB) /* Offsets from base I/O address. */ #define PCNET32_WIO_RDP 0x10 @@ -308,33 +190,52 @@ static int homepna[MAX_UNITS]; #define PCNET32_TOTAL_SIZE 0x20 +#define CSR0 0 +#define CSR0_INIT 0x1 +#define CSR0_START 0x2 +#define CSR0_STOP 0x4 +#define CSR0_TXPOLL 0x8 +#define CSR0_INTEN 0x40 +#define CSR0_IDON 0x0100 +#define CSR0_NORMAL (CSR0_START | CSR0_INTEN) +#define PCNET32_INIT_LOW 1 +#define PCNET32_INIT_HIGH 2 +#define CSR3 3 +#define CSR4 4 +#define CSR5 5 +#define CSR5_SUSPEND 0x0001 +#define CSR15 15 +#define PCNET32_MC_FILTER 8 + +#define PCNET32_79C970A 0x2621 + /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; + __le32 base; + __le16 buf_length; /* two`s complement of length */ + __le16 status; + __le32 msg_length; + __le32 reserved; }; struct pcnet32_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; + __le32 base; + __le16 length; /* two`s complement of length */ + __le16 status; + __le32 misc; + __le32 reserved; }; /* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; + __le16 mode; + __le16 tlen_rlen; + u8 phys_addr[6]; + __le16 reserved; + __le32 filter[2]; /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; + __le32 rx_ring; + __le32 tx_ring; }; /* PCnet32 access functions */ @@ -353,59 +254,60 @@ struct pcnet32_access { * so the structure should be allocated using pci_alloc_consistent(). */ struct pcnet32_private { - struct pcnet32_init_block init_block; + struct pcnet32_init_block *init_block; /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ - struct pcnet32_rx_head *rx_ring; - struct pcnet32_tx_head *tx_ring; - dma_addr_t dma_addr; /* DMA address of beginning of this - object, returned by - pci_alloc_consistent */ - struct pci_dev *pci_dev; /* Pointer to the associated pci device - structure */ - const char *name; + struct pcnet32_rx_head *rx_ring; + struct pcnet32_tx_head *tx_ring; + dma_addr_t init_dma_addr;/* DMA address of beginning of the init block, + returned by pci_alloc_consistent */ + struct pci_dev *pci_dev; + const char *name; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff **tx_skbuff; - struct sk_buff **rx_skbuff; - dma_addr_t *tx_dma_addr; - dma_addr_t *rx_dma_addr; - struct pcnet32_access a; - spinlock_t lock; /* Guard lock */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int rx_ring_size; /* current rx ring size */ - unsigned int tx_ring_size; /* current tx ring size */ - unsigned int rx_mod_mask; /* rx ring modular mask */ - unsigned int tx_mod_mask; /* tx ring modular mask */ - unsigned short rx_len_bits; - unsigned short tx_len_bits; - dma_addr_t rx_ring_dma_addr; - dma_addr_t tx_ring_dma_addr; - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - char tx_full; - char phycount; /* number of phys found */ - int options; - unsigned int shared_irq:1, /* shared irq possible */ - dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ - struct net_device *next; - struct mii_if_info mii_if; - struct timer_list watchdog_timer; - struct timer_list blink_timer; - u32 msg_enable; /* debug message level */ + struct sk_buff **tx_skbuff; + struct sk_buff **rx_skbuff; + dma_addr_t *tx_dma_addr; + dma_addr_t *rx_dma_addr; + struct pcnet32_access a; + spinlock_t lock; /* Guard lock */ + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int rx_ring_size; /* current rx ring size */ + unsigned int tx_ring_size; /* current tx ring size */ + unsigned int rx_mod_mask; /* rx ring modular mask */ + unsigned int tx_mod_mask; /* tx ring modular mask */ + unsigned short rx_len_bits; + unsigned short tx_len_bits; + dma_addr_t rx_ring_dma_addr; + dma_addr_t tx_ring_dma_addr; + unsigned int dirty_rx, /* ring entries to be freed. */ + dirty_tx; + + struct net_device *dev; + struct napi_struct napi; + char tx_full; + char phycount; /* number of phys found */ + int options; + unsigned int shared_irq:1, /* shared irq possible */ + dxsuflo:1, /* disable transmit stop on uflo */ + mii:1; /* mii port available */ + struct net_device *next; + struct mii_if_info mii_if; + struct timer_list watchdog_timer; + struct timer_list blink_timer; + u32 msg_enable; /* debug message level */ /* each bit indicates an available PHY */ - u32 phymask; + u32 phymask; + unsigned short chip_version; /* which variant this is */ }; -static void pcnet32_probe_vlbus(void); static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); static int pcnet32_probe1(unsigned long, int, struct pci_dev *); static int pcnet32_open(struct net_device *); static int pcnet32_init_ring(struct net_device *); -static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); -static int pcnet32_rx(struct net_device *); +static netdev_tx_t pcnet32_start_xmit(struct sk_buff *, + struct net_device *); static void pcnet32_tx_timeout(struct net_device *dev); -static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *); +static irqreturn_t pcnet32_interrupt(int, void *); static int pcnet32_close(struct net_device *); static struct net_device_stats *pcnet32_get_stats(struct net_device *); static void pcnet32_load_multicast(struct net_device *dev); @@ -425,16 +327,10 @@ static int pcnet32_get_regs_len(struct net_device *dev); static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *ptr); static void pcnet32_purge_tx_ring(struct net_device *dev); -static int pcnet32_alloc_ring(struct net_device *dev, char *name); +static int pcnet32_alloc_ring(struct net_device *dev, const char *name); static void pcnet32_free_ring(struct net_device *dev); static void pcnet32_check_media(struct net_device *dev, int verbose); -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, -}; - static u16 pcnet32_wio_read_csr(unsigned long addr, int index) { outw(index, addr + PCNET32_WIO_RAP); @@ -545,18 +441,259 @@ static struct pcnet32_access pcnet32_dwio = { .reset = pcnet32_dwio_reset }; +static void pcnet32_netif_stop(struct net_device *dev) +{ + struct pcnet32_private *lp = netdev_priv(dev); + + dev->trans_start = jiffies; + napi_disable(&lp->napi); + netif_tx_disable(dev); +} + +static void pcnet32_netif_start(struct net_device *dev) +{ + struct pcnet32_private *lp = netdev_priv(dev); + ulong ioaddr = dev->base_addr; + u16 val; + + netif_wake_queue(dev); + val = lp->a.read_csr(ioaddr, CSR3); + val &= 0x00ff; + lp->a.write_csr(ioaddr, CSR3, val); + napi_enable(&lp->napi); +} + +/* + * Allocate space for the new sized tx ring. + * Free old resources + * Save new resources. + * Any failure keeps old resources. + * Must be called with lp->lock held. + */ +static void pcnet32_realloc_tx_ring(struct net_device *dev, + struct pcnet32_private *lp, + unsigned int size) +{ + dma_addr_t new_ring_dma_addr; + dma_addr_t *new_dma_addr_list; + struct pcnet32_tx_head *new_tx_ring; + struct sk_buff **new_skb_list; + + pcnet32_purge_tx_ring(dev); + + new_tx_ring = pci_alloc_consistent(lp->pci_dev, + sizeof(struct pcnet32_tx_head) * + (1 << size), + &new_ring_dma_addr); + if (new_tx_ring == NULL) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Consistent memory allocation failed.\n", + dev->name); + return; + } + memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size)); + + new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t), + GFP_ATOMIC); + if (!new_dma_addr_list) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory allocation failed.\n", dev->name); + goto free_new_tx_ring; + } + + new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *), + GFP_ATOMIC); + if (!new_skb_list) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory allocation failed.\n", dev->name); + goto free_new_lists; + } + + kfree(lp->tx_skbuff); + kfree(lp->tx_dma_addr); + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_tx_head) * + lp->tx_ring_size, lp->tx_ring, + lp->tx_ring_dma_addr); + + lp->tx_ring_size = (1 << size); + lp->tx_mod_mask = lp->tx_ring_size - 1; + lp->tx_len_bits = (size << 12); + lp->tx_ring = new_tx_ring; + lp->tx_ring_dma_addr = new_ring_dma_addr; + lp->tx_dma_addr = new_dma_addr_list; + lp->tx_skbuff = new_skb_list; + return; + + free_new_lists: + kfree(new_dma_addr_list); + free_new_tx_ring: + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_tx_head) * + (1 << size), + new_tx_ring, + new_ring_dma_addr); + return; +} + +/* + * Allocate space for the new sized rx ring. + * Re-use old receive buffers. + * alloc extra buffers + * free unneeded buffers + * free unneeded buffers + * Save new resources. + * Any failure keeps old resources. + * Must be called with lp->lock held. + */ +static void pcnet32_realloc_rx_ring(struct net_device *dev, + struct pcnet32_private *lp, + unsigned int size) +{ + dma_addr_t new_ring_dma_addr; + dma_addr_t *new_dma_addr_list; + struct pcnet32_rx_head *new_rx_ring; + struct sk_buff **new_skb_list; + int new, overlap; + + new_rx_ring = pci_alloc_consistent(lp->pci_dev, + sizeof(struct pcnet32_rx_head) * + (1 << size), + &new_ring_dma_addr); + if (new_rx_ring == NULL) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Consistent memory allocation failed.\n", + dev->name); + return; + } + memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size)); + + new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t), + GFP_ATOMIC); + if (!new_dma_addr_list) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory allocation failed.\n", dev->name); + goto free_new_rx_ring; + } + + new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *), + GFP_ATOMIC); + if (!new_skb_list) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory allocation failed.\n", dev->name); + goto free_new_lists; + } + + /* first copy the current receive buffers */ + overlap = min(size, lp->rx_ring_size); + for (new = 0; new < overlap; new++) { + new_rx_ring[new] = lp->rx_ring[new]; + new_dma_addr_list[new] = lp->rx_dma_addr[new]; + new_skb_list[new] = lp->rx_skbuff[new]; + } + /* now allocate any new buffers needed */ + for (; new < size; new++ ) { + struct sk_buff *rx_skbuff; + new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB); + if (!(rx_skbuff = new_skb_list[new])) { + /* keep the original lists and buffers */ + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: pcnet32_realloc_rx_ring dev_alloc_skb failed.\n", + dev->name); + goto free_all_new; + } + skb_reserve(rx_skbuff, NET_IP_ALIGN); + + new_dma_addr_list[new] = + pci_map_single(lp->pci_dev, rx_skbuff->data, + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); + new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]); + new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE); + new_rx_ring[new].status = cpu_to_le16(0x8000); + } + /* and free any unneeded buffers */ + for (; new < lp->rx_ring_size; new++) { + if (lp->rx_skbuff[new]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new], + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_skbuff[new]); + } + } + + kfree(lp->rx_skbuff); + kfree(lp->rx_dma_addr); + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_rx_head) * + lp->rx_ring_size, lp->rx_ring, + lp->rx_ring_dma_addr); + + lp->rx_ring_size = (1 << size); + lp->rx_mod_mask = lp->rx_ring_size - 1; + lp->rx_len_bits = (size << 4); + lp->rx_ring = new_rx_ring; + lp->rx_ring_dma_addr = new_ring_dma_addr; + lp->rx_dma_addr = new_dma_addr_list; + lp->rx_skbuff = new_skb_list; + return; + + free_all_new: + for (; --new >= lp->rx_ring_size; ) { + if (new_skb_list[new]) { + pci_unmap_single(lp->pci_dev, new_dma_addr_list[new], + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb(new_skb_list[new]); + } + } + kfree(new_skb_list); + free_new_lists: + kfree(new_dma_addr_list); + free_new_rx_ring: + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_rx_head) * + (1 << size), + new_rx_ring, + new_ring_dma_addr); + return; +} + +static void pcnet32_purge_rx_ring(struct net_device *dev) +{ + struct pcnet32_private *lp = netdev_priv(dev); + int i; + + /* free all allocated skbuffs */ + for (i = 0; i < lp->rx_ring_size; i++) { + lp->rx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ + if (lp->rx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(lp->rx_skbuff[i]); + } + lp->rx_skbuff[i] = NULL; + lp->rx_dma_addr[i] = 0; + } +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void pcnet32_poll_controller(struct net_device *dev) { disable_irq(dev->irq); - pcnet32_interrupt(0, dev, NULL); + pcnet32_interrupt(0, dev); enable_irq(dev->irq); } #endif static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; int r = -EOPNOTSUPP; @@ -571,7 +708,7 @@ static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; int r = -EOPNOTSUPP; @@ -586,7 +723,7 @@ static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); @@ -598,16 +735,18 @@ static void pcnet32_get_drvinfo(struct net_device *dev, static u32 pcnet32_get_link(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; int r; spin_lock_irqsave(&lp->lock, flags); if (lp->mii) { r = mii_link_ok(&lp->mii_if); - } else { + } else if (lp->chip_version >= PCNET32_79C970A) { ulong ioaddr = dev->base_addr; /* card base I/O address */ r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } else { /* can not detect link on really old chips */ + r = 1; } spin_unlock_irqrestore(&lp->lock, flags); @@ -616,19 +755,19 @@ static u32 pcnet32_get_link(struct net_device *dev) static u32 pcnet32_get_msglevel(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); return lp->msg_enable; } static void pcnet32_set_msglevel(struct net_device *dev, u32 value) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); lp->msg_enable = value; } static int pcnet32_nway_reset(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; int r = -EOPNOTSUPP; @@ -643,69 +782,66 @@ static int pcnet32_nway_reset(struct net_device *dev) static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); - ering->tx_max_pending = TX_MAX_RING_SIZE - 1; - ering->tx_pending = lp->tx_ring_size - 1; - ering->rx_max_pending = RX_MAX_RING_SIZE - 1; - ering->rx_pending = lp->rx_ring_size - 1; + ering->tx_max_pending = TX_MAX_RING_SIZE; + ering->tx_pending = lp->tx_ring_size; + ering->rx_max_pending = RX_MAX_RING_SIZE; + ering->rx_pending = lp->rx_ring_size; } static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; + unsigned int size; + ulong ioaddr = dev->base_addr; int i; if (ering->rx_mini_pending || ering->rx_jumbo_pending) return -EINVAL; if (netif_running(dev)) - pcnet32_close(dev); + pcnet32_netif_stop(dev); spin_lock_irqsave(&lp->lock, flags); - pcnet32_free_ring(dev); - lp->tx_ring_size = - min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE); - lp->rx_ring_size = - min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE); + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */ + + size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE); /* set the minimum ring size to 4, to allow the loopback test to work * unchanged. */ for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) { - if (lp->tx_ring_size <= (1 << i)) + if (size <= (1 << i)) break; } - lp->tx_ring_size = (1 << i); - lp->tx_mod_mask = lp->tx_ring_size - 1; - lp->tx_len_bits = (i << 12); + if ((1 << i) != lp->tx_ring_size) + pcnet32_realloc_tx_ring(dev, lp, i); + size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE); for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) { - if (lp->rx_ring_size <= (1 << i)) + if (size <= (1 << i)) break; } - lp->rx_ring_size = (1 << i); - lp->rx_mod_mask = lp->rx_ring_size - 1; - lp->rx_len_bits = (i << 4); + if ((1 << i) != lp->rx_ring_size) + pcnet32_realloc_rx_ring(dev, lp, i); - if (pcnet32_alloc_ring(dev, dev->name)) { - pcnet32_free_ring(dev); - spin_unlock_irqrestore(&lp->lock, flags); - return -ENOMEM; + lp->napi.weight = lp->rx_ring_size / 2; + + if (netif_running(dev)) { + pcnet32_netif_start(dev); + pcnet32_restart(dev, CSR0_NORMAL); } spin_unlock_irqrestore(&lp->lock, flags); - if (pcnet32_debug & NETIF_MSG_DRV) - printk(KERN_INFO PFX + if (netif_msg_drv(lp)) + printk(KERN_INFO "%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name, lp->rx_ring_size, lp->tx_ring_size); - if (netif_running(dev)) - pcnet32_open(dev); - return 0; } @@ -715,15 +851,20 @@ static void pcnet32_get_strings(struct net_device *dev, u32 stringset, memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); } -static int pcnet32_self_test_count(struct net_device *dev) +static int pcnet32_get_sset_count(struct net_device *dev, int sset) { - return PCNET32_TEST_LEN; + switch (sset) { + case ETH_SS_TEST: + return PCNET32_TEST_LEN; + default: + return -EOPNOTSUPP; + } } static void pcnet32_ethtool_test(struct net_device *dev, struct ethtool_test *test, u64 * data) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int rc; if (test->flags == ETH_TEST_FL_OFFLINE) { @@ -744,14 +885,14 @@ static void pcnet32_ethtool_test(struct net_device *dev, static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); struct pcnet32_access *a = &lp->a; /* access to registers */ ulong ioaddr = dev->base_addr; /* card base I/O address */ struct sk_buff *skb; /* sk buff */ int x, i; /* counters */ int numbuffs = 4; /* number of TX/RX buffers and descs */ u16 status = 0x8300; /* TX ring status */ - u16 teststatus; /* test of ring status */ + __le16 teststatus; /* test of ring status */ int rc; /* return code */ int size; /* size of packets */ unsigned char *packet; /* source packet data */ @@ -759,29 +900,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) unsigned long flags; unsigned long ticks; - *data1 = 1; /* status of test, default to fail */ rc = 1; /* default to fail */ if (netif_running(dev)) - pcnet32_close(dev); + pcnet32_netif_stop(dev); spin_lock_irqsave(&lp->lock, flags); + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */ + + numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size)); /* Reset the PCNET32 */ lp->a.reset(ioaddr); + lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ /* switch pcnet32 to 32bit mode */ lp->a.write_bcr(ioaddr, 20, 2); - lp->init_block.mode = - le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - lp->init_block.filter[0] = 0; - lp->init_block.filter[1] = 0; - /* purge & init rings but don't actually restart */ pcnet32_restart(dev, 0x0000); - lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */ /* Initialize Transmit buffers. */ size = data_len + 15; @@ -796,7 +935,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) packet = skb->data; skb_put(skb, size); /* create space for data */ lp->tx_skbuff[x] = skb; - lp->tx_ring[x].length = le16_to_cpu(-skb->len); + lp->tx_ring[x].length = cpu_to_le16(-skb->len); lp->tx_ring[x].misc = 0; /* put DA and SA into the skb */ @@ -816,21 +955,21 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[x].base = - (u32) le32_to_cpu(lp->tx_dma_addr[x]); + lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]); wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[x].status = le16_to_cpu(status); + lp->tx_ring[x].status = cpu_to_le16(status); } } - x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ - x = x | 0x0002; - a->write_bcr(ioaddr, 32, x); + x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */ + a->write_bcr(ioaddr, 32, x | 0x0002); - lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */ + /* set int loopback in CSR15 */ + x = a->read_csr(ioaddr, CSR15) & 0xfffc; + lp->a.write_csr(ioaddr, CSR15, x | 0x0044); - teststatus = le16_to_cpu(0x8000); - lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ + teststatus = cpu_to_le16(0x8000); + lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */ /* Check status of descriptors */ for (x = 0; x < numbuffs; x++) { @@ -838,7 +977,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) rmb(); while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) { spin_unlock_irqrestore(&lp->lock, flags); - mdelay(1); + msleep(1); spin_lock_irqsave(&lp->lock, flags); rmb(); ticks++; @@ -851,7 +990,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) } } - lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */ wmb(); if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); @@ -884,33 +1023,32 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) } x++; } - if (!rc) { - *data1 = 0; - } clean_up: + *data1 = rc; pcnet32_purge_tx_ring(dev); - x = a->read_csr(ioaddr, 15) & 0xFFFF; - a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ - x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ - x = x & ~0x0002; - a->write_bcr(ioaddr, 32, x); + x = a->read_csr(ioaddr, CSR15); + a->write_csr(ioaddr, CSR15, (x & ~0x0044)); /* reset bits 6 and 2 */ - spin_unlock_irqrestore(&lp->lock, flags); + x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ + a->write_bcr(ioaddr, 32, (x & ~0x0002)); if (netif_running(dev)) { - pcnet32_open(dev); + pcnet32_netif_start(dev); + pcnet32_restart(dev, CSR0_NORMAL); } else { + pcnet32_purge_rx_ring(dev); lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ } + spin_unlock_irqrestore(&lp->lock, flags); return (rc); } /* end pcnet32_loopback_test */ static void pcnet32_led_blink_callback(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); struct pcnet32_access *a = &lp->a; ulong ioaddr = dev->base_addr; unsigned long flags; @@ -927,7 +1065,7 @@ static void pcnet32_led_blink_callback(struct net_device *dev) static int pcnet32_phys_id(struct net_device *dev, u32 data) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); struct pcnet32_access *a = &lp->a; ulong ioaddr = dev->base_addr; unsigned long flags; @@ -949,6 +1087,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) mod_timer(&lp->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); + /* AV: the limit here makes no sense whatsoever */ if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))) data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ); @@ -965,11 +1104,320 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) return 0; } +/* + * lp->lock must be held. + */ +static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, + int can_sleep) +{ + int csr5; + struct pcnet32_private *lp = netdev_priv(dev); + struct pcnet32_access *a = &lp->a; + ulong ioaddr = dev->base_addr; + int ticks; + + /* really old chips have to be stopped. */ + if (lp->chip_version < PCNET32_79C970A) + return 0; + + /* set SUSPEND (SPND) - CSR5 bit 0 */ + csr5 = a->read_csr(ioaddr, CSR5); + a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND); + + /* poll waiting for bit to be set */ + ticks = 0; + while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) { + spin_unlock_irqrestore(&lp->lock, *flags); + if (can_sleep) + msleep(1); + else + mdelay(1); + spin_lock_irqsave(&lp->lock, *flags); + ticks++; + if (ticks > 200) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG + "%s: Error getting into suspend!\n", + dev->name); + return 0; + } + } + return 1; +} + +/* + * process one receive descriptor entry + */ + +static void pcnet32_rx_entry(struct net_device *dev, + struct pcnet32_private *lp, + struct pcnet32_rx_head *rxp, + int entry) +{ + int status = (short)le16_to_cpu(rxp->status) >> 8; + int rx_in_place = 0; + struct sk_buff *skb; + short pkt_len; + + if (status != 0x03) { /* There was an error. */ + /* + * There is a tricky error noted by John Murphy, + * to Russ Nelson: Even with full-sized + * buffers it's possible for a jabber packet to use two + * buffers, with only the last correctly noting the error. + */ + if (status & 0x01) /* Only count a general error at the */ + dev->stats.rx_errors++; /* end of a packet. */ + if (status & 0x20) + dev->stats.rx_frame_errors++; + if (status & 0x10) + dev->stats.rx_over_errors++; + if (status & 0x08) + dev->stats.rx_crc_errors++; + if (status & 0x04) + dev->stats.rx_fifo_errors++; + return; + } + + pkt_len = (le32_to_cpu(rxp->msg_length) & 0xfff) - 4; + + /* Discard oversize frames. */ + if (unlikely(pkt_len > PKT_BUF_SIZE)) { + if (netif_msg_drv(lp)) + printk(KERN_ERR "%s: Impossible packet size %d!\n", + dev->name, pkt_len); + dev->stats.rx_errors++; + return; + } + if (pkt_len < 60) { + if (netif_msg_rx_err(lp)) + printk(KERN_ERR "%s: Runt packet!\n", dev->name); + dev->stats.rx_errors++; + return; + } + + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + + if ((newskb = dev_alloc_skb(PKT_BUF_SKB))) { + skb_reserve(newskb, NET_IP_ALIGN); + skb = lp->rx_skbuff[entry]; + pci_unmap_single(lp->pci_dev, + lp->rx_dma_addr[entry], + PKT_BUF_SIZE, + PCI_DMA_FROMDEVICE); + skb_put(skb, pkt_len); + lp->rx_skbuff[entry] = newskb; + lp->rx_dma_addr[entry] = + pci_map_single(lp->pci_dev, + newskb->data, + PKT_BUF_SIZE, + PCI_DMA_FROMDEVICE); + rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]); + rx_in_place = 1; + } else + skb = NULL; + } else { + skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN); + } + + if (skb == NULL) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory squeeze, dropping packet.\n", + dev->name); + dev->stats.rx_dropped++; + return; + } + if (!rx_in_place) { + skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, pkt_len); /* Make room */ + pci_dma_sync_single_for_cpu(lp->pci_dev, + lp->rx_dma_addr[entry], + pkt_len, + PCI_DMA_FROMDEVICE); + skb_copy_to_linear_data(skb, + (unsigned char *)(lp->rx_skbuff[entry]->data), + pkt_len); + pci_dma_sync_single_for_device(lp->pci_dev, + lp->rx_dma_addr[entry], + pkt_len, + PCI_DMA_FROMDEVICE); + } + dev->stats.rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + dev->stats.rx_packets++; + return; +} + +static int pcnet32_rx(struct net_device *dev, int budget) +{ + struct pcnet32_private *lp = netdev_priv(dev); + int entry = lp->cur_rx & lp->rx_mod_mask; + struct pcnet32_rx_head *rxp = &lp->rx_ring[entry]; + int npackets = 0; + + /* If we own the next entry, it's a new packet. Send it up. */ + while (npackets < budget && (short)le16_to_cpu(rxp->status) >= 0) { + pcnet32_rx_entry(dev, lp, rxp, entry); + npackets += 1; + /* + * The docs say that the buffer length isn't touched, but Andrew + * Boyd of QNX reports that some revs of the 79C965 clear it. + */ + rxp->buf_length = cpu_to_le16(NEG_BUF_SIZE); + wmb(); /* Make sure owner changes after others are visible */ + rxp->status = cpu_to_le16(0x8000); + entry = (++lp->cur_rx) & lp->rx_mod_mask; + rxp = &lp->rx_ring[entry]; + } + + return npackets; +} + +static int pcnet32_tx(struct net_device *dev) +{ + struct pcnet32_private *lp = netdev_priv(dev); + unsigned int dirty_tx = lp->dirty_tx; + int delta; + int must_restart = 0; + + while (dirty_tx != lp->cur_tx) { + int entry = dirty_tx & lp->tx_mod_mask; + int status = (short)le16_to_cpu(lp->tx_ring[entry].status); + + if (status < 0) + break; /* It still hasn't been Txed */ + + lp->tx_ring[entry].base = 0; + + if (status & 0x4000) { + /* There was a major error, log it. */ + int err_status = le32_to_cpu(lp->tx_ring[entry].misc); + dev->stats.tx_errors++; + if (netif_msg_tx_err(lp)) + printk(KERN_ERR + "%s: Tx error status=%04x err_status=%08x\n", + dev->name, status, + err_status); + if (err_status & 0x04000000) + dev->stats.tx_aborted_errors++; + if (err_status & 0x08000000) + dev->stats.tx_carrier_errors++; + if (err_status & 0x10000000) + dev->stats.tx_window_errors++; +#ifndef DO_DXSUFLO + if (err_status & 0x40000000) { + dev->stats.tx_fifo_errors++; + /* Ackk! On FIFO errors the Tx unit is turned off! */ + /* Remove this verbosity later! */ + if (netif_msg_tx_err(lp)) + printk(KERN_ERR + "%s: Tx FIFO error!\n", + dev->name); + must_restart = 1; + } +#else + if (err_status & 0x40000000) { + dev->stats.tx_fifo_errors++; + if (!lp->dxsuflo) { /* If controller doesn't recover ... */ + /* Ackk! On FIFO errors the Tx unit is turned off! */ + /* Remove this verbosity later! */ + if (netif_msg_tx_err(lp)) + printk(KERN_ERR + "%s: Tx FIFO error!\n", + dev->name); + must_restart = 1; + } + } +#endif + } else { + if (status & 0x1800) + dev->stats.collisions++; + dev->stats.tx_packets++; + } + + /* We must free the original skb */ + if (lp->tx_skbuff[entry]) { + pci_unmap_single(lp->pci_dev, + lp->tx_dma_addr[entry], + lp->tx_skbuff[entry]-> + len, PCI_DMA_TODEVICE); + dev_kfree_skb_any(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = NULL; + lp->tx_dma_addr[entry] = 0; + } + dirty_tx++; + } + + delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size); + if (delta > lp->tx_ring_size) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, lp->cur_tx, + lp->tx_full); + dirty_tx += lp->tx_ring_size; + delta -= lp->tx_ring_size; + } + + if (lp->tx_full && + netif_queue_stopped(dev) && + delta < lp->tx_ring_size - 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + netif_wake_queue(dev); + } + lp->dirty_tx = dirty_tx; + + return must_restart; +} + +static int pcnet32_poll(struct napi_struct *napi, int budget) +{ + struct pcnet32_private *lp = container_of(napi, struct pcnet32_private, napi); + struct net_device *dev = lp->dev; + unsigned long ioaddr = dev->base_addr; + unsigned long flags; + int work_done; + u16 val; + + work_done = pcnet32_rx(dev, budget); + + spin_lock_irqsave(&lp->lock, flags); + if (pcnet32_tx(dev)) { + /* reset the chip to clear the error condition, then restart */ + lp->a.reset(ioaddr); + lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ + pcnet32_restart(dev, CSR0_START); + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + + if (work_done < budget) { + spin_lock_irqsave(&lp->lock, flags); + + __napi_complete(napi); + + /* clear interrupt masks */ + val = lp->a.read_csr(ioaddr, CSR3); + val &= 0x00ff; + lp->a.write_csr(ioaddr, CSR3, val); + + /* Set interrupt enable. */ + lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); + + spin_unlock_irqrestore(&lp->lock, flags); + } + return work_done; +} + #define PCNET32_REGS_PER_PHY 32 #define PCNET32_MAX_PHYS 32 static int pcnet32_get_regs_len(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int j = lp->phycount * PCNET32_REGS_PER_PHY; return ((PCNET32_NUM_REGS + j) * sizeof(u16)); @@ -980,35 +1428,16 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, { int i, csr0; u16 *buff = ptr; - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); struct pcnet32_access *a = &lp->a; ulong ioaddr = dev->base_addr; - int ticks; unsigned long flags; spin_lock_irqsave(&lp->lock, flags); - csr0 = a->read_csr(ioaddr, 0); - if (!(csr0 & 0x0004)) { /* If not stopped */ - /* set SUSPEND (SPND) - CSR5 bit 0 */ - a->write_csr(ioaddr, 5, 0x0001); - - /* poll waiting for bit to be set */ - ticks = 0; - while (!(a->read_csr(ioaddr, 5) & 0x0001)) { - spin_unlock_irqrestore(&lp->lock, flags); - mdelay(1); - spin_lock_irqsave(&lp->lock, flags); - ticks++; - if (ticks > 200) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG - "%s: Error getting into suspend!\n", - dev->name); - break; - } - } - } + csr0 = a->read_csr(ioaddr, CSR0); + if (!(csr0 & CSR0_STOP)) /* If not stopped */ + pcnet32_suspend(dev, &flags, 1); /* read address PROM */ for (i = 0; i < 16; i += 2) @@ -1045,15 +1474,18 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, } } - if (!(csr0 & 0x0004)) { /* If not stopped */ + if (!(csr0 & CSR0_STOP)) { /* If not stopped */ + int csr5; + /* clear SUSPEND (SPND) - CSR5 bit 0 */ - a->write_csr(ioaddr, 5, 0x0000); + csr5 = a->read_csr(ioaddr, CSR5); + a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND)); } spin_unlock_irqrestore(&lp->lock, flags); } -static struct ethtool_ops pcnet32_ethtool_ops = { +static const struct ethtool_ops pcnet32_ethtool_ops = { .get_settings = pcnet32_get_settings, .set_settings = pcnet32_set_settings, .get_drvinfo = pcnet32_get_drvinfo, @@ -1063,22 +1495,18 @@ static struct ethtool_ops pcnet32_ethtool_ops = { .get_link = pcnet32_get_link, .get_ringparam = pcnet32_get_ringparam, .set_ringparam = pcnet32_set_ringparam, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, .get_strings = pcnet32_get_strings, - .self_test_count = pcnet32_self_test_count, .self_test = pcnet32_ethtool_test, .phys_id = pcnet32_phys_id, .get_regs_len = pcnet32_get_regs_len, .get_regs = pcnet32_get_regs, - .get_perm_addr = ethtool_op_get_perm_addr, + .get_sset_count = pcnet32_get_sset_count, }; /* only probes for non-PCI devices, the rest are handled by * pci_register_driver via pcnet32_probe_pci */ -static void __devinit pcnet32_probe_vlbus(void) +static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist) { unsigned int *port, ioaddr; @@ -1141,6 +1569,22 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } +static const struct net_device_ops pcnet32_netdev_ops = { + .ndo_open = pcnet32_open, + .ndo_stop = pcnet32_close, + .ndo_start_xmit = pcnet32_start_xmit, + .ndo_tx_timeout = pcnet32_tx_timeout, + .ndo_get_stats = pcnet32_get_stats, + .ndo_set_multicast_list = pcnet32_set_multicast_list, + .ndo_do_ioctl = pcnet32_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = pcnet32_poll_controller, +#endif +}; + /* pcnet32_probe1 * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. * pdev will be NULL when called from pcnet32_probe_vlbus. @@ -1149,7 +1593,6 @@ static int __devinit pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) { struct pcnet32_private *lp; - dma_addr_t lp_dma_addr; int i, media; int fdx, mii, fset, dxsuflo; int chip_version; @@ -1170,8 +1613,11 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { a = &pcnet32_dwio; - } else + } else { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX "No access methods\n"); goto err_release_region; + } } chip_version = @@ -1271,14 +1717,16 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dxsuflo = 1; } - dev = alloc_etherdev(0); + dev = alloc_etherdev(sizeof(*lp)); if (!dev) { if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_ERR PFX "Memory allocation failed.\n"); ret = -ENOMEM; goto err_release_region; } - SET_NETDEV_DEV(dev, &pdev->dev); + + if (pdev) + SET_NETDEV_DEV(dev, &pdev->dev); if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); @@ -1287,8 +1735,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) * station address PROM at the base address and programmed into the * "Physical Address Registers" CSR12-14. * As a precautionary measure, we read the PROM values and complain if - * they disagree with the CSRs. Either way, we use the CSR values, and - * double check that they are valid. + * they disagree with the CSRs. If they miscompare, and the PROM addr + * is valid, then the PROM addr is used. */ for (i = 0; i < 3; i++) { unsigned int val; @@ -1320,67 +1768,63 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); if (pcnet32_debug & NETIF_MSG_PROBE) { - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i]); + printk(" %pM", dev->dev_addr); /* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) { i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i); + printk(KERN_INFO " tx_start_pt(0x%04x):", i); switch (i >> 10) { case 0: - printk(" 20 bytes,"); + printk(KERN_CONT " 20 bytes,"); break; case 1: - printk(" 64 bytes,"); + printk(KERN_CONT " 64 bytes,"); break; case 2: - printk(" 128 bytes,"); + printk(KERN_CONT " 128 bytes,"); break; case 3: - printk("~220 bytes,"); + printk(KERN_CONT "~220 bytes,"); break; } i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(" BCR18(%x):", i & 0xffff); + printk(KERN_CONT " BCR18(%x):", i & 0xffff); if (i & (1 << 5)) - printk("BurstWrEn "); + printk(KERN_CONT "BurstWrEn "); if (i & (1 << 6)) - printk("BurstRdEn "); + printk(KERN_CONT "BurstRdEn "); if (i & (1 << 7)) - printk("DWordIO "); + printk(KERN_CONT "DWordIO "); if (i & (1 << 11)) - printk("NoUFlow "); + printk(KERN_CONT "NoUFlow "); i = a->read_bcr(ioaddr, 25); - printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8); + printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 26); - printk(" SRAM_BND=0x%04x,", i << 8); + printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 27); if (i & (1 << 14)) - printk("LowLatRx"); + printk(KERN_CONT "LowLatRx"); } } dev->base_addr = ioaddr; + lp = netdev_priv(dev); /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ - if ((lp = - pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { + if ((lp->init_block = + pci_alloc_consistent(pdev, sizeof(*lp->init_block), &lp->init_dma_addr)) == NULL) { if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_ERR PFX "Consistent memory allocation failed.\n"); ret = -ENOMEM; goto err_free_netdev; } - - memset(lp, 0, sizeof(*lp)); - lp->dma_addr = lp_dma_addr; lp->pci_dev = pdev; + lp->dev = dev; + spin_lock_init(&lp->lock); - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - dev->priv = lp; lp->name = chipname; lp->shared_irq = shared; lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */ @@ -1394,9 +1838,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->mii_if.reg_num_mask = 0x1f; lp->dxsuflo = dxsuflo; lp->mii = mii; + lp->chip_version = chip_version; lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) - || (options[cards_found] > sizeof(options_mapping))) + || (options[cards_found] >= sizeof(options_mapping))) lp->options = PCNET32_PORT_ASEL; else lp->options = options_mapping[options[cards_found]]; @@ -1404,16 +1849,15 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->mii_if.mdio_read = mdio_read; lp->mii_if.mdio_write = mdio_write; + /* napi.weight is used in both the napi and non-napi cases */ + lp->napi.weight = lp->rx_ring_size / 2; + + netif_napi_add(dev, &lp->napi, pcnet32_poll, lp->rx_ring_size / 2); + if (fdx && !(lp->options & PCNET32_PORT_ASEL) && ((cards_found >= MAX_UNITS) || full_duplex[cards_found])) lp->options |= PCNET32_PORT_FD; - if (!a) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "No access methods\n"); - ret = -ENODEV; - goto err_free_consistent; - } lp->a = *a; /* prior to register_netdev, dev->name is not yet correct */ @@ -1426,23 +1870,21 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) && dev->dev_addr[2] == 0x75) lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; - lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ - lp->init_block.tlen_rlen = - le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + lp->init_block->mode = cpu_to_le16(0x0003); /* Disable Rx and Tx. */ + lp->init_block->tlen_rlen = + cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + lp->init_block->phys_addr[i] = dev->dev_addr[i]; + lp->init_block->filter[0] = 0x00000000; + lp->init_block->filter[1] = 0x00000000; + lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr); + lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr); /* switch pcnet32 to 32bit mode */ a->write_bcr(ioaddr, 20, 2); - a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, - init_block)) & 0xffff); - a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, - init_block)) >> 16); + a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff)); + a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16)); if (pdev) { /* use the IRQ provided by PCI */ dev->irq = pdev->irq; @@ -1457,7 +1899,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) * boards will work. */ /* Trigger an initialization just for the interrupt. */ - a->write_csr(ioaddr, 0, 0x41); + a->write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT); mdelay(1); dev->irq = probe_irq_off(irq_mask); @@ -1507,20 +1949,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->watchdog_timer.function = (void *)&pcnet32_watchdog; /* The PCNET32-specific entries in the device structure. */ - dev->open = &pcnet32_open; - dev->hard_start_xmit = &pcnet32_start_xmit; - dev->stop = &pcnet32_close; - dev->get_stats = &pcnet32_get_stats; - dev->set_multicast_list = &pcnet32_set_multicast_list; - dev->do_ioctl = &pcnet32_ioctl; + dev->netdev_ops = &pcnet32_netdev_ops; dev->ethtool_ops = &pcnet32_ethtool_ops; - dev->tx_timeout = pcnet32_tx_timeout; dev->watchdog_timeo = (5 * HZ); -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = pcnet32_poll_controller; -#endif - /* Fill in the generic fields of the device structure. */ if (register_netdev(dev)) goto err_free_ring; @@ -1541,29 +1973,29 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) return 0; - err_free_ring: +err_free_ring: pcnet32_free_ring(dev); - err_free_consistent: - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - err_free_netdev: + pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block), + lp->init_block, lp->init_dma_addr); +err_free_netdev: free_netdev(dev); - err_release_region: +err_release_region: release_region(ioaddr, PCNET32_TOTAL_SIZE); return ret; } /* if any allocation fails, caller must also call pcnet32_free_ring */ -static int pcnet32_alloc_ring(struct net_device *dev, char *name) +static int pcnet32_alloc_ring(struct net_device *dev, const char *name) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size, &lp->tx_ring_dma_addr); if (lp->tx_ring == NULL) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; @@ -1574,59 +2006,55 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name) lp->rx_ring_size, &lp->rx_ring_dma_addr); if (lp->rx_ring == NULL) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; } - lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, + lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t), GFP_ATOMIC); if (!lp->tx_dma_addr) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } - memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size); - lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, + lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t), GFP_ATOMIC); if (!lp->rx_dma_addr) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } - memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size); - lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, + lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *), GFP_ATOMIC); if (!lp->tx_skbuff) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } - memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size); - lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, + lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *), GFP_ATOMIC); if (!lp->rx_skbuff) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX + if (netif_msg_drv(lp)) + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } - memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size); return 0; } static void pcnet32_free_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); kfree(lp->tx_skbuff); lp->tx_skbuff = NULL; @@ -1659,15 +2087,16 @@ static void pcnet32_free_ring(struct net_device *dev) static int pcnet32_open(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); + struct pci_dev *pdev = lp->pci_dev; unsigned long ioaddr = dev->base_addr; u16 val; int i; int rc; unsigned long flags; - if (request_irq(dev->irq, &pcnet32_interrupt, - lp->shared_irq ? SA_SHIRQ : 0, dev->name, + if (request_irq(dev->irq, pcnet32_interrupt, + lp->shared_irq ? IRQF_SHARED : 0, dev->name, (void *)dev)) { return -EAGAIN; } @@ -1690,8 +2119,7 @@ static int pcnet32_open(struct net_device *dev) "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", dev->name, dev->irq, (u32) (lp->tx_ring_dma_addr), (u32) (lp->rx_ring_dma_addr), - (u32) (lp->dma_addr + - offsetof(struct pcnet32_private, init_block))); + (u32) (lp->init_dma_addr)); /* set/reset autoselect bit */ val = lp->a.read_bcr(ioaddr, 2) & ~2; @@ -1708,10 +2136,7 @@ static int pcnet32_open(struct net_device *dev) val |= 2; } else if (lp->options & PCNET32_PORT_ASEL) { /* workaround of xSeries250, turn on for 79C975 only */ - i = ((lp->a.read_csr(ioaddr, 88) | - (lp->a. - read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff; - if (i == 0x2627) + if (lp->chip_version == 0x2627) val |= 3; } lp->a.write_bcr(ioaddr, 9, val); @@ -1724,9 +2149,9 @@ static int pcnet32_open(struct net_device *dev) lp->a.write_csr(ioaddr, 124, val); /* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */ - if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT && - (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX || - lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) { + if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT && + (pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX || + pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) { if (lp->options & PCNET32_PORT_ASEL) { lp->options = PCNET32_PORT_FD | PCNET32_PORT_100; if (netif_msg_link(lp)) @@ -1827,14 +2252,14 @@ static int pcnet32_open(struct net_device *dev) #ifdef DO_DXSUFLO if (lp->dxsuflo) { /* Disable transmit stop on underflow */ - val = lp->a.read_csr(ioaddr, 3); + val = lp->a.read_csr(ioaddr, CSR3); val |= 0x40; - lp->a.write_csr(ioaddr, 3, val); + lp->a.write_csr(ioaddr, CSR3, val); } #endif - lp->init_block.mode = - le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + lp->init_block->mode = + cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); pcnet32_load_multicast(dev); if (pcnet32_init_ring(dev)) { @@ -1842,40 +2267,39 @@ static int pcnet32_open(struct net_device *dev) goto err_free_ring; } + napi_enable(&lp->napi); + /* Re-initialize the PCNET32, and start it when done. */ - lp->a.write_csr(ioaddr, 1, (lp->dma_addr + - offsetof(struct pcnet32_private, - init_block)) & 0xffff); - lp->a.write_csr(ioaddr, 2, - (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)) >> 16); + lp->a.write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff)); + lp->a.write_csr(ioaddr, 2, (lp->init_dma_addr >> 16)); - lp->a.write_csr(ioaddr, 4, 0x0915); - lp->a.write_csr(ioaddr, 0, 0x0001); + lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ + lp->a.write_csr(ioaddr, CSR0, CSR0_INIT); netif_start_queue(dev); - /* Print the link status and start the watchdog */ - pcnet32_check_media(dev, 1); - mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); + if (lp->chip_version >= PCNET32_79C970A) { + /* Print the link status and start the watchdog */ + pcnet32_check_media(dev, 1); + mod_timer(&lp->watchdog_timer, PCNET32_WATCHDOG_TIMEOUT); + } i = 0; while (i++ < 100) - if (lp->a.read_csr(ioaddr, 0) & 0x0100) + if (lp->a.read_csr(ioaddr, CSR0) & CSR0_IDON) break; /* * We used to clear the InitDone bit, 0x0100, here but Mark Stockton * reports that doing so triggers a bug in the '974. */ - lp->a.write_csr(ioaddr, 0, 0x0042); + lp->a.write_csr(ioaddr, CSR0, CSR0_NORMAL); if (netif_msg_ifup(lp)) printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", dev->name, i, - (u32) (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)), - lp->a.read_csr(ioaddr, 0)); + (u32) (lp->init_dma_addr), + lp->a.read_csr(ioaddr, CSR0)); spin_unlock_irqrestore(&lp->lock, flags); @@ -1883,18 +2307,7 @@ static int pcnet32_open(struct net_device *dev) err_free_ring: /* free any allocated skbuffs */ - for (i = 0; i < lp->rx_ring_size; i++) { - lp->rx_ring[i].status = 0; - if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_skbuff[i]); - } - lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; - } - - pcnet32_free_ring(dev); + pcnet32_purge_rx_ring(dev); /* * Switch back to 16bit mode to avoid problems with dumb @@ -1923,7 +2336,7 @@ static int pcnet32_open(struct net_device *dev) static void pcnet32_purge_tx_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int i; for (i = 0; i < lp->tx_ring_size; i++) { @@ -1943,7 +2356,7 @@ static void pcnet32_purge_tx_ring(struct net_device *dev) /* Initialize the PCNET32 Rx and Tx rings. */ static int pcnet32_init_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int i; lp->tx_full = 0; @@ -1955,26 +2368,26 @@ static int pcnet32_init_ring(struct net_device *dev) if (rx_skbuff == NULL) { if (! (rx_skbuff = lp->rx_skbuff[i] = - dev_alloc_skb(PKT_BUF_SZ))) { + dev_alloc_skb(PKT_BUF_SKB))) { /* there is not much, we can do at this point */ - if (pcnet32_debug & NETIF_MSG_DRV) + if (netif_msg_drv(lp)) printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n", dev->name); return -1; } - skb_reserve(rx_skbuff, 2); + skb_reserve(rx_skbuff, NET_IP_ALIGN); } rmb(); if (lp->rx_dma_addr[i] == 0) lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data, - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - lp->rx_ring[i].base = (u32) le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); + lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]); + lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE); wmb(); /* Make sure owner changes after all others are visible */ - lp->rx_ring[i].status = le16_to_cpu(0x8000); + lp->rx_ring[i].status = cpu_to_le16(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear * the upper ownership bit. */ @@ -1985,12 +2398,12 @@ static int pcnet32_init_ring(struct net_device *dev) lp->tx_dma_addr[i] = 0; } - lp->init_block.tlen_rlen = - le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + lp->init_block->tlen_rlen = + cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + lp->init_block->phys_addr[i] = dev->dev_addr[i]; + lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr); + lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr); wmb(); /* Make sure all changes are visible */ return 0; } @@ -2001,13 +2414,13 @@ static int pcnet32_init_ring(struct net_device *dev) */ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; int i; /* wait for stop */ for (i = 0; i < 100; i++) - if (lp->a.read_csr(ioaddr, 0) & 0x0004) + if (lp->a.read_csr(ioaddr, CSR0) & CSR0_STOP) break; if (i >= 100 && netif_msg_drv(lp)) @@ -2020,18 +2433,18 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) return; /* ReInit Ring */ - lp->a.write_csr(ioaddr, 0, 1); + lp->a.write_csr(ioaddr, CSR0, CSR0_INIT); i = 0; while (i++ < 1000) - if (lp->a.read_csr(ioaddr, 0) & 0x0100) + if (lp->a.read_csr(ioaddr, CSR0) & CSR0_IDON) break; - lp->a.write_csr(ioaddr, 0, csr0_bits); + lp->a.write_csr(ioaddr, CSR0, csr0_bits); } static void pcnet32_tx_timeout(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr, flags; spin_lock_irqsave(&lp->lock, flags); @@ -2039,9 +2452,9 @@ static void pcnet32_tx_timeout(struct net_device *dev) if (pcnet32_debug & NETIF_MSG_DRV) printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - lp->a.write_csr(ioaddr, 0, 0x0004); - lp->stats.tx_errors++; + dev->name, lp->a.read_csr(ioaddr, CSR0)); + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); + dev->stats.tx_errors++; if (netif_msg_tx_err(lp)) { int i; printk(KERN_DEBUG @@ -2062,7 +2475,7 @@ static void pcnet32_tx_timeout(struct net_device *dev) le16_to_cpu(lp->tx_ring[i].status)); printk("\n"); } - pcnet32_restart(dev, 0x0042); + pcnet32_restart(dev, CSR0_NORMAL); dev->trans_start = jiffies; netif_wake_queue(dev); @@ -2070,9 +2483,10 @@ static void pcnet32_tx_timeout(struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); } -static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb, + struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; u16 status; int entry; @@ -2083,7 +2497,7 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) if (netif_msg_tx_queued(lp)) { printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); + dev->name, lp->a.read_csr(ioaddr, CSR0)); } /* Default status -- will not enable Successful-TxDone @@ -2099,22 +2513,22 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Caution: the write order is important here, set the status * with the "ownership" bits last. */ - lp->tx_ring[entry].length = le16_to_cpu(-skb->len); + lp->tx_ring[entry].length = cpu_to_le16(-skb->len); lp->tx_ring[entry].misc = 0x00000000; lp->tx_skbuff[entry] = skb; lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[entry].base = (u32) le32_to_cpu(lp->tx_dma_addr[entry]); + lp->tx_ring[entry].base = cpu_to_le32(lp->tx_dma_addr[entry]); wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[entry].status = le16_to_cpu(status); + lp->tx_ring[entry].status = cpu_to_le16(status); lp->cur_tx++; - lp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; /* Trigger an immediate send poll. */ - lp->a.write_csr(ioaddr, 0, 0x0048); + lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL); dev->trans_start = jiffies; @@ -2123,168 +2537,53 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } spin_unlock_irqrestore(&lp->lock, flags); - return 0; + return NETDEV_TX_OK; } /* The PCNET32 interrupt handler. */ static irqreturn_t -pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) +pcnet32_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct pcnet32_private *lp; unsigned long ioaddr; - u16 csr0, rap; + u16 csr0; int boguscnt = max_interrupt_work; - int must_restart; - - if (!dev) { - if (pcnet32_debug & NETIF_MSG_INTR) - printk(KERN_DEBUG "%s(): irq %d for unknown device\n", - __FUNCTION__, irq); - return IRQ_NONE; - } ioaddr = dev->base_addr; - lp = dev->priv; + lp = netdev_priv(dev); spin_lock(&lp->lock); - rap = lp->a.read_rap(ioaddr); - while ((csr0 = lp->a.read_csr(ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) { + csr0 = lp->a.read_csr(ioaddr, CSR0); + while ((csr0 & 0x8f00) && --boguscnt >= 0) { if (csr0 == 0xffff) { break; /* PCMCIA remove happened */ } /* Acknowledge all of the current interrupt sources ASAP. */ - lp->a.write_csr(ioaddr, 0, csr0 & ~0x004f); - - must_restart = 0; + lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, lp->a.read_csr(ioaddr, 0)); - - if (csr0 & 0x0400) /* Rx interrupt */ - pcnet32_rx(dev); - - if (csr0 & 0x0200) { /* Tx-done interrupt */ - unsigned int dirty_tx = lp->dirty_tx; - int delta; - - while (dirty_tx != lp->cur_tx) { - int entry = dirty_tx & lp->tx_mod_mask; - int status = - (short)le16_to_cpu(lp->tx_ring[entry]. - status); - - if (status < 0) - break; /* It still hasn't been Txed */ - - lp->tx_ring[entry].base = 0; - - if (status & 0x4000) { - /* There was an major error, log it. */ - int err_status = - le32_to_cpu(lp->tx_ring[entry]. - misc); - lp->stats.tx_errors++; - if (netif_msg_tx_err(lp)) - printk(KERN_ERR - "%s: Tx error status=%04x err_status=%08x\n", - dev->name, status, - err_status); - if (err_status & 0x04000000) - lp->stats.tx_aborted_errors++; - if (err_status & 0x08000000) - lp->stats.tx_carrier_errors++; - if (err_status & 0x10000000) - lp->stats.tx_window_errors++; -#ifndef DO_DXSUFLO - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - if (netif_msg_tx_err(lp)) - printk(KERN_ERR - "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } -#else - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - if (!lp->dxsuflo) { /* If controller doesn't recover ... */ - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - if (netif_msg_tx_err - (lp)) - printk(KERN_ERR - "%s: Tx FIFO error! CSR0=%4.4x\n", - dev-> - name, - csr0); - must_restart = 1; - } - } -#endif - } else { - if (status & 0x1800) - lp->stats.collisions++; - lp->stats.tx_packets++; - } - - /* We must free the original skb */ - if (lp->tx_skbuff[entry]) { - pci_unmap_single(lp->pci_dev, - lp->tx_dma_addr[entry], - lp->tx_skbuff[entry]-> - len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = NULL; - lp->tx_dma_addr[entry] = 0; - } - dirty_tx++; - } - - delta = - (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + - lp->tx_ring_size); - if (delta > lp->tx_ring_size) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, - lp->tx_full); - dirty_tx += lp->tx_ring_size; - delta -= lp->tx_ring_size; - } - - if (lp->tx_full && - netif_queue_stopped(dev) && - delta < lp->tx_ring_size - 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - netif_wake_queue(dev); - } - lp->dirty_tx = dirty_tx; - } + dev->name, csr0, lp->a.read_csr(ioaddr, CSR0)); /* Log misc errors. */ if (csr0 & 0x4000) - lp->stats.tx_errors++; /* Tx babble. */ + dev->stats.tx_errors++; /* Tx babble. */ if (csr0 & 0x1000) { /* - * this happens when our receive ring is full. This shouldn't - * be a problem as we will see normal rx interrupts for the frames - * in the receive ring. But there are some PCI chipsets (I can - * reproduce this on SP3G with Intel saturn chipset) which have - * sometimes problems and will fill up the receive ring with - * error descriptors. In this situation we don't get a rx - * interrupt, but a missed frame interrupt sooner or later. - * So we try to clean up our receive ring here. + * This happens when our receive ring is full. This + * shouldn't be a problem as we will see normal rx + * interrupts for the frames in the receive ring. But + * there are some PCI chipsets (I can reproduce this + * on SP3G with Intel saturn chipset) which have + * sometimes problems and will fill up the receive + * ring with error descriptors. In this situation we + * don't get a rx interrupt, but a missed frame + * interrupt sooner or later. */ - pcnet32_rx(dev); - lp->stats.rx_errors++; /* Missed a Rx frame. */ + dev->stats.rx_errors++; /* Missed a Rx frame. */ } if (csr0 & 0x0800) { if (netif_msg_drv(lp)) @@ -2293,207 +2592,50 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev->name, csr0); /* unlike for the lance, there is no restart needed */ } - - if (must_restart) { - /* reset the chip to clear the error condition, then restart */ - lp->a.reset(ioaddr); - lp->a.write_csr(ioaddr, 4, 0x0915); - pcnet32_restart(dev, 0x0002); - netif_wake_queue(dev); + if (napi_schedule_prep(&lp->napi)) { + u16 val; + /* set interrupt masks */ + val = lp->a.read_csr(ioaddr, CSR3); + val |= 0x5f00; + lp->a.write_csr(ioaddr, CSR3, val); + + __napi_schedule(&lp->napi); + break; } + csr0 = lp->a.read_csr(ioaddr, CSR0); } - /* Set interrupt enable. */ - lp->a.write_csr(ioaddr, 0, 0x0040); - lp->a.write_rap(ioaddr, rap); - if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); + dev->name, lp->a.read_csr(ioaddr, CSR0)); spin_unlock(&lp->lock); return IRQ_HANDLED; } -static int pcnet32_rx(struct net_device *dev) -{ - struct pcnet32_private *lp = dev->priv; - int entry = lp->cur_rx & lp->rx_mod_mask; - int boguscnt = lp->rx_ring_size / 2; - - /* If we own the next entry, it's a new packet. Send it up. */ - while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { - int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; - - if (status != 0x03) { /* There was an error. */ - /* - * There is a tricky error noted by John Murphy, - * to Russ Nelson: Even with full-sized - * buffers it's possible for a jabber packet to use two - * buffers, with only the last correctly noting the error. - */ - if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet. */ - if (status & 0x20) - lp->stats.rx_frame_errors++; - if (status & 0x10) - lp->stats.rx_over_errors++; - if (status & 0x08) - lp->stats.rx_crc_errors++; - if (status & 0x04) - lp->stats.rx_fifo_errors++; - lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); - } else { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = - (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff) - - 4; - struct sk_buff *skb; - - /* Discard oversize frames. */ - if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Impossible packet size %d!\n", - dev->name, pkt_len); - lp->stats.rx_errors++; - } else if (pkt_len < 60) { - if (netif_msg_rx_err(lp)) - printk(KERN_ERR "%s: Runt packet!\n", - dev->name); - lp->stats.rx_errors++; - } else { - int rx_in_place = 0; - - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - - if ((newskb = - dev_alloc_skb(PKT_BUF_SZ))) { - skb_reserve(newskb, 2); - skb = lp->rx_skbuff[entry]; - pci_unmap_single(lp->pci_dev, - lp-> - rx_dma_addr - [entry], - PKT_BUF_SZ - 2, - PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_len); - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; - lp->rx_dma_addr[entry] = - pci_map_single(lp->pci_dev, - newskb->data, - PKT_BUF_SZ - - 2, - PCI_DMA_FROMDEVICE); - lp->rx_ring[entry].base = - le32_to_cpu(lp-> - rx_dma_addr - [entry]); - rx_in_place = 1; - } else - skb = NULL; - } else { - skb = dev_alloc_skb(pkt_len + 2); - } - - if (skb == NULL) { - int i; - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory squeeze, deferring packet.\n", - dev->name); - for (i = 0; i < lp->rx_ring_size; i++) - if ((short) - le16_to_cpu(lp-> - rx_ring[(entry + - i) - & lp-> - rx_mod_mask]. - status) < 0) - break; - - if (i > lp->rx_ring_size - 2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status |= - le16_to_cpu(0x8000); - wmb(); /* Make sure adapter sees owner change */ - lp->cur_rx++; - } - break; - } - skb->dev = dev; - if (!rx_in_place) { - skb_reserve(skb, 2); /* 16 byte align */ - skb_put(skb, pkt_len); /* Make room */ - pci_dma_sync_single_for_cpu(lp->pci_dev, - lp-> - rx_dma_addr - [entry], - PKT_BUF_SZ - - 2, - PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, - (unsigned char *)(lp-> - rx_skbuff - [entry]-> - data), - pkt_len, 0); - pci_dma_sync_single_for_device(lp-> - pci_dev, - lp-> - rx_dma_addr - [entry], - PKT_BUF_SZ - - 2, - PCI_DMA_FROMDEVICE); - } - lp->stats.rx_bytes += skb->len; - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - } - } - /* - * The docs say that the buffer length isn't touched, but Andrew Boyd - * of QNX reports that some revs of the 79C965 clear it. - */ - lp->rx_ring[entry].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); - wmb(); /* Make sure owner changes after all others are visible */ - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - entry = (++lp->cur_rx) & lp->rx_mod_mask; - if (--boguscnt <= 0) - break; /* don't stay in loop forever */ - } - - return 0; -} - static int pcnet32_close(struct net_device *dev) { unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; - int i; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; del_timer_sync(&lp->watchdog_timer); netif_stop_queue(dev); + napi_disable(&lp->napi); spin_lock_irqsave(&lp->lock, flags); - lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); + dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); if (netif_msg_ifdown(lp)) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); + dev->name, lp->a.read_csr(ioaddr, CSR0)); /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ - lp->a.write_csr(ioaddr, 0, 0x0004); + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* * Switch back to 16bit mode to avoid problems with dumb @@ -2507,31 +2649,8 @@ static int pcnet32_close(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); - /* free all allocated skbuffs */ - for (i = 0; i < lp->rx_ring_size; i++) { - lp->rx_ring[i].status = 0; - wmb(); /* Make sure adapter sees owner change */ - if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_skbuff[i]); - } - lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; - } - - for (i = 0; i < lp->tx_ring_size; i++) { - lp->tx_ring[i].status = 0; /* CPU owns buffer */ - wmb(); /* Make sure adapter sees owner change */ - if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], - lp->tx_skbuff[i]->len, - PCI_DMA_TODEVICE); - dev_kfree_skb(lp->tx_skbuff[i]); - } - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; - } + pcnet32_purge_rx_ring(dev); + pcnet32_purge_tx_ring(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -2540,35 +2659,37 @@ static int pcnet32_close(struct net_device *dev) static struct net_device_stats *pcnet32_get_stats(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; - u16 saved_addr; unsigned long flags; spin_lock_irqsave(&lp->lock, flags); - saved_addr = lp->a.read_rap(ioaddr); - lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); - lp->a.write_rap(ioaddr, saved_addr); + dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); spin_unlock_irqrestore(&lp->lock, flags); - return &lp->stats; + return &dev->stats; } /* taken from the sunlance driver, which it took from the depca driver */ static void pcnet32_load_multicast(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - volatile struct pcnet32_init_block *ib = &lp->init_block; - volatile u16 *mcast_table = (u16 *) & ib->filter; + struct pcnet32_private *lp = netdev_priv(dev); + volatile struct pcnet32_init_block *ib = lp->init_block; + volatile __le16 *mcast_table = (__le16 *)ib->filter; struct dev_mc_list *dmi = dev->mc_list; + unsigned long ioaddr = dev->base_addr; char *addrs; int i; u32 crc; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { - ib->filter[0] = 0xffffffff; - ib->filter[1] = 0xffffffff; + ib->filter[0] = cpu_to_le32(~0U); + ib->filter[1] = cpu_to_le32(~0U); + lp->a.write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff); + lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff); + lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff); + lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff); return; } /* clear the multicast filter */ @@ -2586,10 +2707,11 @@ static void pcnet32_load_multicast(struct net_device *dev) crc = ether_crc_le(6, addrs); crc = crc >> 26; - mcast_table[crc >> 4] = - le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) | - (1 << (crc & 0xf))); + mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf)); } + for (i = 0; i < 4; i++) + lp->a.write_csr(ioaddr, PCNET32_MC_FILTER + i, + le16_to_cpu(mcast_table[i])); return; } @@ -2599,26 +2721,38 @@ static void pcnet32_load_multicast(struct net_device *dev) static void pcnet32_set_multicast_list(struct net_device *dev) { unsigned long ioaddr = dev->base_addr, flags; - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); + int csr15, suspended; spin_lock_irqsave(&lp->lock, flags); + suspended = pcnet32_suspend(dev, &flags, 0); + csr15 = lp->a.read_csr(ioaddr, CSR15); if (dev->flags & IFF_PROMISC) { /* Log any net taps. */ if (netif_msg_hw(lp)) printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - lp->init_block.mode = - le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << + lp->init_block->mode = + cpu_to_le16(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); + lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000); } else { - lp->init_block.mode = - le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + lp->init_block->mode = + cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); + lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff); pcnet32_load_multicast(dev); } - lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ - pcnet32_restart(dev, 0x0042); /* Resume normal operation */ - netif_wake_queue(dev); + if (suspended) { + int csr5; + /* clear SUSPEND (SPND) - CSR5 bit 0 */ + csr5 = lp->a.read_csr(ioaddr, CSR5); + lp->a.write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND)); + } else { + lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); + pcnet32_restart(dev, CSR0_NORMAL); + netif_wake_queue(dev); + } spin_unlock_irqrestore(&lp->lock, flags); } @@ -2626,7 +2760,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev) /* This routine assumes that the lp->lock is held */ static int mdio_read(struct net_device *dev, int phy_id, int reg_num) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; u16 val_out; @@ -2642,7 +2776,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg_num) /* This routine assumes that the lp->lock is held */ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; if (!lp->mii) @@ -2654,7 +2788,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int rc; unsigned long flags; @@ -2672,7 +2806,7 @@ static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int pcnet32_check_otherphy(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); struct mii_if_info mii = lp->mii_if; u16 bmcr; int i; @@ -2719,7 +2853,7 @@ static int pcnet32_check_otherphy(struct net_device *dev) static void pcnet32_check_media(struct net_device *dev, int verbose) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); int curr_link; int prev_link = netif_carrier_ok(dev) ? 1 : 0; u32 bcr9; @@ -2775,7 +2909,7 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) static void pcnet32_watchdog(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; /* Print the link status if it has changed */ @@ -2783,7 +2917,34 @@ static void pcnet32_watchdog(struct net_device *dev) pcnet32_check_media(dev, 0); spin_unlock_irqrestore(&lp->lock, flags); - mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); + mod_timer(&lp->watchdog_timer, round_jiffies(PCNET32_WATCHDOG_TIMEOUT)); +} + +static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (netif_running(dev)) { + netif_device_detach(dev); + pcnet32_close(dev); + } + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int pcnet32_pm_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (netif_running(dev)) { + pcnet32_open(dev); + netif_device_attach(dev); + } + return 0; } static void __devexit pcnet32_remove_one(struct pci_dev *pdev) @@ -2791,12 +2952,13 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = netdev_priv(dev); unregister_netdev(dev); pcnet32_free_ring(dev); release_region(dev->base_addr, PCNET32_TOTAL_SIZE); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block), + lp->init_block, lp->init_dma_addr); free_netdev(dev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -2808,6 +2970,8 @@ static struct pci_driver pcnet32_driver = { .probe = pcnet32_probe_pci, .remove = __devexit_p(pcnet32_remove_one), .id_table = pcnet32_pci_tbl, + .suspend = pcnet32_pm_suspend, + .resume = pcnet32_pm_resume, }; /* An additional parameter that may be passed in... */ @@ -2853,12 +3017,12 @@ static int __init pcnet32_init_module(void) tx_start = tx_start_pt; /* find the PCI devices */ - if (!pci_module_init(&pcnet32_driver)) + if (!pci_register_driver(&pcnet32_driver)) pcnet32_have_pci = 1; /* should we find any remaining VLbus devices ? */ if (pcnet32vlb) - pcnet32_probe_vlbus(); + pcnet32_probe_vlbus(pcnet32_portlist); if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE)) printk(KERN_INFO PFX "%d cards_found.\n", cards_found); @@ -2871,12 +3035,13 @@ static void __exit pcnet32_cleanup_module(void) struct net_device *next_dev; while (pcnet32_dev) { - struct pcnet32_private *lp = pcnet32_dev->priv; + struct pcnet32_private *lp = netdev_priv(pcnet32_dev); next_dev = lp->next; unregister_netdev(pcnet32_dev); pcnet32_free_ring(pcnet32_dev); release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block), + lp->init_block, lp->init_dma_addr); free_netdev(pcnet32_dev); pcnet32_dev = next_dev; }